28.02.2014 Views

Burke_et_al-NIL_Reference_Manual_0286-1984

Burke_et_al-NIL_Reference_Manual_0286-1984

Burke_et_al-NIL_Reference_Manual_0286-1984

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>NIL</strong> <strong>Reference</strong> Manu<strong>al</strong><br />

corresponding to<br />

Release 0.286<br />

January <strong>1984</strong><br />

Glenn S. <strong>Burke</strong><br />

George J. Carr<strong>et</strong>te<br />

Christopher R. Eliot<br />

This report describes ongoing research at the Laboratory for Computer Science of the<br />

Massachus<strong>et</strong>ts Institute of Technology. Support for this research was provided by the Defense<br />

Advanced Research Projects Agency of the Deparuncnt of Defense monitored by the Office of<br />

Nav<strong>al</strong> Research under contract NOO015-75-C-066 1 and N00014·83-K -0125. and by Digit<strong>al</strong><br />

. Equipment Corporation of ~1aynard Massachus<strong>et</strong>ts, with grants of equipment.<br />

CA~1BRIDGE<br />

MASSACHUSJ:n's INS1TruTEOFTECHNOJ.OGY<br />

LABORATORY FOR COMPUTER SCIENCE<br />

MASSACHUSErrS 02139


• • ~ ~ ~ • ~ .. ¥~ • ..'<br />

Abstract<br />

This document describes <strong>NIL</strong>. a New Implementation of Lisp. <strong>NIL</strong> is currently under<br />

development on the DEC VAX under the VAX/VMS operattng system.<br />

Acknowledgments<br />

The chapter on defstruct is a worko\'er of. the chapter appearing in [3]. by Alan Bawden:<br />

added in(lcclIracies are solcly the nUllt of GSB. howe\ er. The chapter on the loop maCfO is a<br />

revision of an earlief published memo [5] which <strong>al</strong>so has appeared in I -isp Machine manu<strong>al</strong>s [12].<br />

'1l1e chaptef on flm'ors was written in part by Patrick SobaIvarro.<br />

documentation are the work of Christopher Eliot.<br />

The editor and its<br />

The interfaces to many functions and .fc'lcilities. and somc of the terminology used in this<br />

document. ~lre taken or derived from thosc used in the ('0\1:\10' I.lSP manu<strong>al</strong> [1]: in particular.<br />

the tCl1llinology llsed for describing scopc and ex/clll in chapter J.<br />

The section on format (section 19.6. page 187) is a reworking of a chapter appearing in [3].<br />

pans of which had earlier appeared in [12] and are the work of Guy Sleele.<br />

Dedication<br />

This publication is dedicated to Randy Davis, may his 750 never crash.<br />

Note<br />

Any comments, suggestions, or criticisms will be welcomed.<br />

n<strong>et</strong>work mail to BUG-<strong>NIL</strong>@MIT-MC.<br />

Please send Arpa or Chaos<br />

Those not on the Arpan<strong>et</strong> may send U.S. mail to<br />

Glenn S. <strong>Burke</strong><br />

Laboratory for Computer Science<br />

545 Technology Square<br />

Cambridge, Mass. 02139<br />

The Arpa n<strong>et</strong>work mail distribution list for announcements pertaining to f\;Il is norm<strong>al</strong>ly used<br />

for announcements about the facilities described here. Contact the author to be placed on it.<br />

- ... - ~ • • - "'~ < ,poo"!, 1.", .... ~ •<br />

'" ~ '" . ~ ~<br />

- • ~ .~~ '" • ~·"'A - - # ~ \ • ~ •• ~<br />

- - (', .<br />

_ 'II: ... • _ '....-v ,


Document History<br />

Earlier versions of this document were distributed as <strong>NIL</strong> Noles for Release 0 (in two revisions).<br />

and <strong>NIL</strong> Noles for Release 0.159. This update corresponds to <strong>NIL</strong> release 0.286, Lisp. system<br />

version 286. It will be revised and reissued with each new Nll. release; because of the constant<br />

changes, it is not the picturc·pcrfcct copy we would like.<br />

Addition<strong>al</strong> Publications<br />

This manu<strong>al</strong>, and other pubJic~ltions~ arc available from the J.ab for Computer Science<br />

Puhlicmions office<br />

MIT LCS Publications<br />

545 Technology Squa~e<br />

Cambridge. MA 02129<br />

who should he contacted directly k)r bibUogr


<strong>NIL</strong> Manu<strong>al</strong><br />

Summary Table of Contents<br />

Sunlmary rrable of Contents<br />

1. Introduction .<br />

2. Dak1 Types.<br />

3. Scope. Extent. and Binding .<br />

4. Predicates ..<br />

5. Programming Constructs .<br />

6. Declarations .<br />

7. Sequences<br />

8. I.isis .<br />

9. Symhols<br />

10. Numbers<br />

11. Characters.<br />

12. Arrays.<br />

13. Strings.<br />

14. Hashing.<br />

15. Packages<br />

16. Defstruct<br />

17. The LOOP Iteration Macro<br />

18. The Flavor Facility<br />

19. Input. Output. and Streams<br />

20. Syntax. . .<br />

21. Debugging and Melering<br />

22. Errors. .. . .<br />

23. Environment Enquiries<br />

24. Compilation. .<br />

25. Introduction to the STEVE editor .<br />

26. The Patch Facility.<br />

27. T<strong>al</strong>king to <strong>NIL</strong> ....... .<br />

28. Peripher<strong>al</strong> Utilities. . . . . .<br />

29. Foreign Language Interface.<br />

30. What Will Break ..<br />

<strong>Reference</strong>s. ..<br />

Concept Index. . .<br />

Message Index. . .<br />

Resource Index . •<br />

Variable and Constant Index. . .<br />

Function, Macro, and Speci<strong>al</strong> Form Index . .<br />

1<br />

3<br />

.11<br />

.16<br />

.22<br />

.41<br />

.48<br />

.56<br />

.65<br />

.71<br />

.94<br />

103<br />

112<br />

118<br />

121<br />

125<br />

144<br />

170<br />

179<br />

213<br />

220<br />

· 229<br />

232<br />

· 243<br />

· 249<br />

280<br />

· 287<br />

295<br />

· 298<br />

· 301<br />

· 307<br />

· 308<br />

· 310<br />

· 311<br />

312<br />

· 314<br />

23-DEC-83


T.lbJc of Contents<br />

ji<br />

<strong>NIL</strong> Manu •• 1<br />

Table of Contents<br />

1. Introduction. . .<br />

1.1 Conventions .. . . . . . . . . . . .<br />

2. I )<strong>al</strong>~1 Types . . .<br />

2.1 Numbers ....<br />

2.1.1 Rarillfl<strong>al</strong>s. . .<br />

2.1.2 "'loafing-point Numbers ..<br />

2.1.] Complex Numbers.<br />

2.2 Characters . . . .<br />

2.3 Symhols . . . . . • . .<br />

2.4 l.ists c:md Conscs . . .<br />

2.5 Armys and Sequences.<br />

2J) Structures. . . . . . .<br />

2.7 Functions .•.....<br />

2.8 Random .mern<strong>al</strong> Types. .<br />

2.8.1 Minisubrs •.•..•.<br />

2.8.2 Modules. . . . . . . .<br />

2.8.3 I nlernaJ Markers. . . .<br />

2.8.4 Unused Types. . . • .<br />

2.9 Coercion . • . . . • . • .<br />

3. Scope. Extent. and Binding •<br />

. . . . .<br />

. . . .- .<br />

. . . . .<br />

. ,. . . . .<br />

... 1<br />

. 1<br />

. 3<br />

. .•. 3<br />

. . 3<br />

· .. 4<br />

· .. s<br />

. . s<br />

· .. 6<br />

· 6<br />

· 7<br />

· 7<br />

. ...... 7<br />

· 8<br />

· 8<br />

· 8<br />

. . . . . . 8<br />

...... 9<br />

. ... 9<br />

. . . . . .<br />

. . . . .<br />

3.1 '..41mbda Application . . . . . . . . 11<br />

13<br />

4. Predicates. . • . . . • • • .<br />

4.1 Type Predicates ..... .<br />

4J.l Type Specifiers .... .<br />

4.1.2 Gcner<strong>al</strong> Type Predicates •.•<br />

4.1.3 Specific Type Predicates .•<br />

4.2 Equ<strong>al</strong>ity Predicates • • • • • .<br />

.- .<br />

· . . . .. . . .<br />

5. Programming Constructs . • • . . . • • •<br />

5.1 Compositions. • • • . .. • • • . • . • • • .<br />

5.2 Definition Fonns. • • • • . • • . • • • •<br />

5.2.1 Defining Functions. • . • • . . • • . •<br />

5.2.2 Defining Macros. • • • . . . • •<br />

5.2.3 Defining Variables. • . • •••••<br />

5.2.4 ControHing Ev<strong>al</strong>uation TIme. • . • . • • • . . •<br />

5.3 Binding and Assignment . . • • • . • • . • • • . •<br />

5.3.1 Dynamic<strong>al</strong>ly Binding Variable Variables ..•.•<br />

5.4 Condition<strong>al</strong>s . . . • . • . . • . • • . . • . . •<br />

5.5 Function Invocation. • • •<br />

5.6 Iteration Constructs. • • •<br />

5.6.1 Mapping Functions ..<br />

5.6.2 Othcr Iteration Forms •<br />

5.6.3 BJock and Tagbody. . .<br />

.<br />

. .<br />

. . . . . .<br />

. . . . . .<br />

· . . . . . . .<br />

· . . .. . . . .<br />

.'. .<br />

· . . . . . .<br />

· . . . . . . .<br />

· .. . .<br />

· . . . . · . . . . . . . . ... .<br />

. . . . . . .. . . . . . . .. . . . . . . . .<br />

.. . . . . . . . . . . . . . . . . . . . . .<br />

e. • • • • • • • e" • • • • • • • • • • • • • • •<br />

. . . . .<br />

. . . . . .<br />

. . . . . .<br />

16-<br />

16<br />

16<br />

18<br />

18<br />

20<br />

22<br />

22<br />

22<br />

22<br />

23<br />

24<br />

2S<br />

2S<br />

27<br />

28<br />

30<br />

31<br />

31<br />

32<br />

34<br />

23-DEC-8J


Nil. Manu<strong>al</strong><br />

iii<br />

Table of Contents<br />

5.7 Non-I.ocat Flow ufControI ..<br />

5.8 Multiple V<strong>al</strong>ues ....<br />

5.9 Gener<strong>al</strong>ized Variables<br />

5.10 Property Lists ...<br />

6. Declarations . . . . . . . .<br />

6.1 Loc<strong>al</strong> Declarations . .<br />

6.1.1 The Speci<strong>al</strong> Declaration . . .... .<br />

6.l.2 Declarations Affecting Vari~lble Bindings.<br />

6.1.3 Declarations Affecting Compilation Strategies . .<br />

6.2 Proclamations: Giuhat Dechlrations<br />

6.3 Declaring the Types of ronns. . .<br />

7. Sequences . . . . . . . . . .<br />

7.1 Accessing Sequences .... .<br />

7.2 Creating New Sequences .... .<br />

7.J Searching through Sequenccs .. .<br />

7.4 M iscelJaneolls Operations on Sequences.<br />

7.5 Iteration over Sequences ..... .<br />

7.6 Sorting Sequences . . . . . . .. . . . .<br />

8. Lists . . . . . . . . . . . . . . . . . . .<br />

8.1 Creating. Accessing, and Modifying List Structure.<br />

8.2 Substitution . . .<br />

8.' lJsine f .~sts as S~ts<br />

8.4 Association Lists . .<br />

9. Symbols ...... .<br />

9.1 The Property List ..<br />

. 9.2 Thc Print Name ..<br />

9.3 Creating Symbols ..<br />

9.4 The V<strong>al</strong>ue and Function Cells.<br />

9.5 Addition<strong>al</strong> Names . . .<br />

9.6 Symbol Concatcntation ..<br />

9.7 Intern<strong>al</strong> Routines. . • . .<br />

10. Numbers •.......<br />

10.1 Types. Contagion, Coercion. and Confusion.<br />

10.1.1 The Types . . . . . . . .<br />

10.1.2 Contagion and Coercion.<br />

10.1.3 Confusion ....... .<br />

10.2 Predicates on Numbers ..<br />

10.3 Comparisons on Numbers. .<br />

. 10.4 Arithm<strong>et</strong>ic Operations ...<br />

10.5 Irration<strong>al</strong> and Transcendent<strong>al</strong> Functions.<br />

10.5.1 Exponenti<strong>al</strong> and I.ogarithmic Functions ..<br />

10.5.2 Trigonom<strong>et</strong>ric and Related Functions. . .<br />

10.6 Numeric Type Conversions •........<br />

10.7 Integer Convcrsion and SpeciaJized Division. . .<br />

35<br />

36<br />

38<br />

39<br />

41<br />

41<br />

43<br />

44<br />

45<br />

46<br />

47<br />

48<br />

49<br />

50<br />

51<br />

52<br />

54<br />

55<br />

56<br />

56<br />

. ..... 60<br />

61<br />

63<br />

65<br />

65<br />

66<br />

66<br />

68<br />

69<br />

70<br />

70<br />

71<br />

71<br />

71<br />

72<br />

72<br />

73<br />

. .... 73<br />

74<br />

76<br />

76<br />

77<br />

78<br />

79<br />

23-DEC-83<br />

, .... , j


T~lble ofC(}ntcnt~<br />

iv<br />

N II. M~l1lwtl<br />

10.8 I.ogic<strong>al</strong> Operations on Numbers .<br />

]0.9 Byte Manipul~ti()n Functions.<br />

10.10 Random Numbers .....<br />

10.11 Fixnum-Only Arithm<strong>et</strong>ic ..<br />

10.11.1 Comparisons. ..... .<br />

10.11.2 Arithm<strong>et</strong>ic Operations ..<br />

10,11.3 Bits and Bytes. . .. . .<br />

10.11.4 'Inc Super-Primitives ..<br />

10.12 Double-Float-Oniy Arithm<strong>et</strong>ic ...<br />

10.13 Decomposition of Floating Point Numbers . .<br />

10.14 Implementation Constants<br />

11. Characters. . . . . . . . . . .'. . . . . .<br />

] 1.1 Pred icates on Ch.lractcrs. . . . . . .<br />

11.2 Ch


<strong>NIL</strong> Manu<strong>al</strong><br />

v<br />

Table of Contents<br />

16. Dcf.~truct . . . . . .<br />

16.1 Introduction .....<br />

16.2 A Simple Examplc<br />

16.3 Syntax of def.~truct<br />

16.4 Options to defstruct. .<br />

16.4.1 :type. . . . .<br />

16.4.2 :constructor .<br />

16.4.3 :<strong>al</strong>tcrant .<br />

16.4.4 :namcd..<br />

16.4.5 :prcdicatc<br />

16.4.6 :print ..<br />

16.4.7 :dcfault-pointcr<br />

16.4.8 :conc-name. .<br />

16.4.9 :inc1ude .... .<br />

16.4.10 :copier .... .<br />

16.4.11 :class-symboJ ..'<br />

16.4.12 :sfa-function<br />

16.4.13 :sfa-name ..<br />

16.4.14 :sizc-symbo1.<br />

16.4.15 :size-macro . .- .<br />

16.4.16 :initi<strong>al</strong>-offs<strong>et</strong><br />

16.4.17 : but-first . .<br />

16.4.18 :c<strong>al</strong>lablc-acccssors..<br />

i6.4J9 :evai-when ......... .<br />

16.4.20 :property .... .<br />

16.4.21 A Type Used As An Option .<br />

16.4.22 Other Options ..•.....<br />

16.5 The dcfstrucl-dcscriplion Structurc<br />

16.6 Extensions to dcfstruct . . . . . .<br />

16.6.1 A Simple Example ...... .<br />

16.6.2 Syntax of defstruct-definc-type .<br />

16.6.3 Options to defstruct-define-type.<br />

16.6.3.1 :cons . . . .<br />

16.6.3.2 :ref....<br />

16.6.3.3 :predjcate.<br />

16.6.3.4 :overhead.<br />

16.6.3.5 :named . •<br />

16.6.3.6 : keywords . .<br />

16.6.3.7 :defstruct-options • •<br />

16.6.3.8 :dcfstruct ..•...<br />

16.6.3.9 :copier . . . . . . .<br />

16.6.3.10 :implcmentations. .<br />

. .',.<br />

. : .<br />

. . '.<br />

· .. 125<br />

· . 125<br />

· .. 125<br />

· . 126<br />

· . 127<br />

· .. 127<br />

· 128<br />

· 129<br />

· .. 131<br />

· .. 131<br />

· 131<br />

.132<br />

.132<br />

· 133<br />

· .134<br />

· 134<br />

· 134<br />

· 135<br />

.135<br />

· .135<br />

.135<br />

.... 135<br />

. . . .. .136<br />

.136<br />

.136<br />

.136<br />

.137<br />

.137<br />

.138<br />

· . 138<br />

· .139<br />

· •. 139<br />

.139<br />

· ...•. 140<br />

· . 141<br />

.141<br />

· ••••• 141<br />

.142<br />

.142<br />

· .142<br />

· .143<br />

. .•. 143<br />

17. The LOOP Iteration Macro<br />

17.1 Introduction. . . . . . . .<br />

17.2 Clauses. . . . . . . .' . .<br />

17.2.1 Itcration-Driving Clauses ....<br />

· ..... 144<br />

· .144<br />

.145<br />

· .. 146<br />

23-DEC-83<br />

~.r~ ~ _ ~ ,,~~~C w' " •<br />

., -' - _ - ': .w ~ ~ -r' ~"" _ ~"_ ..-.<br />

, . ,<br />

-- - - ~<br />

~~. ~,,, ,'" ~ ~ .'


'I' •• hlc of C()ntcnt.~<br />

vi<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

17.2.2 Bindings .....<br />

17.2.3 Entr~mce and Exit.<br />

17.2.4 Side Effects.<br />

17.2.5 V<strong>al</strong>ues ..... .<br />

17 .2.6 Endtest.~ . . . . .<br />

17.2.7 Aggregated Boolean Tests.<br />

17.2.8 Condirion<strong>al</strong>il.ation . . ..<br />

17.2.9 Miscellaneous Other Clauses<br />

17 J I.oop Synonyms ..<br />

17.4 Data Types . . . • . . .<br />

17.5 Dcstructuring •.....<br />

17.6 'I'hc Itcrcllion Framework<br />

17.7 Iteration Paths. . . . . • , .<br />

17.7.1 Prc-Defined Paths ...<br />

17.7.1.1 The Interned-Symbols Path<br />

17.7.1.2 Seq uence Iteration. ... . . . .<br />

17.7.2 Defining Paths ....... .<br />

17.7.2.1 /\ 11 Example Path Definition .<br />

18. Thc rlavor Facility. . . . . . . • ..<br />

18.1 Introduction. . . . . . . . . . . . . • . . .<br />

18.1.1 Object-oriented Programming ......•.•.<br />

18.1.2 Objcct-oriented Programming Using flavors.. . .<br />

IR.2 System-nefincci M~AAges . ... . ..<br />

18.3 Message Defaults . . . . . ....<br />

19. Input. Output, and Streams.<br />

19.1 Standard Streams ....<br />

19.2 Strcam Creation and Operations ...... .<br />

19.3 Input Functions. • . •...<br />

19.3.1 Ascii Input. . 0 • 0 • • • • • 0 ••<br />

19.3.2 Binary Input . • • 0 • • • • • 0 ••<br />

19.4 Output Functions. . •.•..• 0 ••<br />

19.4.1 Ascii Output . . • . • • . • 0 • • • • ••<br />

19.4.2 Binary Output ....••..•..•..<br />

19.5 Fonnatted Output ....<br />

19.6 Format 0 • • • • 0 • • •<br />

19.6.1 The Operators • 0 0 •<br />

19.6.2 Defining your own ..<br />

. ..<br />

19.7 Qucrying the User 0 •• 0<br />

19.8 FHesystem Interface 0.' 0.' • • •••••<br />

19.8.1 Pathnarnes • . • • • . .. • • • • . • • . . . .<br />

19.8.1.1 Pathnarne Functions. '0 • • • •••••<br />

19.8.1.2 Merging and Defaulting •••••...••••<br />

19.8.2 Opening Files. . • . . • •.•••<br />

19.8.3 Other File Operations. . ..•.<br />

19.8.4 File Matching. • . • . . •<br />

· . 149<br />

· .. 150<br />

· . lSI<br />

· .. 151<br />

· 153<br />

· 154<br />

· 154<br />

· . 156<br />

· .. 157<br />

· 157<br />

· .. 158<br />

· 159<br />

· .. 161<br />

· . 162<br />

· 162<br />

· .. 163<br />

• }()4<br />

· .. 167<br />

· . 170<br />

· .. 170<br />

· .. 170<br />

· .. 171<br />

· 176<br />

· . 177<br />

· .. 179<br />

.179<br />

· .180<br />

. .•.. 183<br />

· . 183<br />

.184<br />

· 184<br />

· .. 185<br />

· .• 186<br />

· ..• 186<br />

• • 187<br />

· .. 188<br />

• • 194<br />

· . 197<br />

· .197<br />

· ... 198<br />

· •• 199<br />

· ..• 200<br />

· .. 202<br />

• .. 203<br />

• •• 204<br />

23-DEC-83


_...... L • ~<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

vii<br />

Table of Contents<br />

19.8.5 Loading files .................... .<br />

19.8.6 filc Attribute Lists ................ .<br />

19.8.7 Intcrn<strong>al</strong>s for VMS Record Management Scrvices .... .<br />

19.8.7.1 Data Stnlcturcs ...... .<br />

19.8.7.2 RMS and Related Hacking. ...... .<br />

19.9 Tcrmin<strong>al</strong>llO ............... .<br />

19.9.1 Modifying the Termin<strong>al</strong> Characteristics ..<br />

19.9.2 Making More Tennin<strong>al</strong> Streams<br />

. ~. .<br />

19.9.3 Display 'ITY Mcssages ..<br />

20. Syntax ........... .<br />

20.1 What the Reader Tolerates.<br />

20.1.1 Backquote . .<br />

20.2 'Inc Lisp Reader ... .<br />

20.2.1 Introduction ... .<br />

20.2.2 Reader Extensions.<br />

20.2.3 Readtable . . . '. .<br />

20.2.4 Alternative Syntax .<br />

21. Dcbugging and Mctering<br />

21.1 I-low of Control ....<br />

21.1.1 Tracing. . . . . . .<br />

21.1.2 Who does Wha~ and Where.<br />

21.2 Examining Objects . . . .<br />

21.3 Ucbug and Breakpoints . .<br />

21.4 M<strong>et</strong>ering ...... .<br />

21.4.1 Timing. . . . . .<br />

21.4.2 Function C<strong>al</strong>ling .<br />

21.5 System Management<br />

21.5.1 An example . • .<br />

21.5.2 "Source (Re)Compilation" ..<br />

21.5.3 Information in Modules<br />

21.5.4 Related Utilities .<br />

21.6 Verification . . • • • •<br />

22. Errors .....•...•<br />

23. Environment Enquiries<br />

23.1 The Host Environment . •<br />

23.2 Mac1isp-Compatihle Status Enquiries .<br />

23.3 Privileges. . . • .<br />

23.4 Memory Usage . . • . . .<br />

23.5 Time and Date . • • . . •<br />

23.5.1 The Main Functions • • •<br />

23.5.2 Printing Dates and Times.<br />

23.5.3 Namings. . . . . • . • •<br />

23.5.4 Timezones. . . . . . . .<br />

23.5.5 Miscellaneous Other Functions.<br />

· .204<br />

· .205<br />

.207<br />

· .207<br />

· .208<br />

.209<br />

· . 211<br />

· .211<br />

· .212<br />

. ...... 213<br />

· . 213<br />

· .216<br />

.217<br />

. .. 217<br />

· .218<br />

· .218<br />

· .219<br />

. 220<br />

· .220<br />

· .220<br />

.221<br />

· .222<br />

.222<br />

.223<br />

.223<br />

· .224<br />

· .226<br />

· . 226<br />

.227<br />

.228<br />

.228<br />

.228<br />

.229<br />

· 232<br />

.232<br />

• ......... 232<br />

· 233<br />

· 234<br />

.234<br />

.235<br />

.235<br />

• . 236<br />

.238<br />

.238<br />

23-DEC-83<br />

".... . ~<br />

• ~ - - - ~ ~ • • "... - j<br />

. .'<br />

. , . . - ' .<br />

• • _ _ _ •• ~_ o. • ~<br />

~ , • _ " • _. • • _ _ ". •<br />

'.<br />

• • •


Table of Contents<br />

viii<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

23.5.6 Variations in Daylight Savings Time. . . . . . .<br />

23.5.7 Intern<strong>al</strong> Conversions . '0 0 ........ 0 0 0<br />

23.5.8 Brain Damage . . 0<br />

23.6 Job/Process and System Infonnation. . . . •<br />

• • • • • • • • • • • • • " • • •<br />

24. Compilation . . . . . . . . . . . . . . • . . .<br />

24.1 Interaction Control. . . . • . . . . . . . . .. . . .<br />

24.2 Efficiency. Optimization, and Benchmarking .•.•<br />

.239<br />

... 240<br />

. .240<br />

.241<br />

.243<br />

. 246<br />

.246<br />

249<br />

25. Introduction to thc STEVE editor ..... • 0 • • • • •<br />

25.1 Introduction. . . . . • . • . .. . . . . . . . . 249<br />

25.2 Gctting Started • . . . . . . . . . . . . . . . 249<br />

25.3 Editing Files ... 0 • • • • • • • • 250<br />

25.4 Modifying the buffer. . • • . • . • . 254<br />

25.4.1 The Simplest Commands . . • . . . . . . . . . . 254<br />

25.4.2 Now that you know the Simplest Commands . • . . . . 255<br />

25.4.2.1 Numeric Arguments" .•.... • · • . . . . . . • . . . . .. 255<br />

25.4.2.2 Control-X. . . . . . • . • 0 0 • • • • ". • • • • • • • • • • • • • • • •<br />

25.4.2.3 Mcta-X and Control-M<strong>et</strong>a-X. . . . . . . . . . . . . .<br />

256<br />

. 256<br />

25.4.2.4 Marks and Regions. . . . . . . . . . . . . . . . . . . . . . . . . . 257<br />

25.4.2.5 KiUing and Un-kiJIing . • . . eo • .. • • • • • • • • • • 0 0 • • • • • • • • •<br />

25.4.2.6 List Oriented Commands. • . . • . · • • . . . . . . .<br />

257<br />

. 258<br />

25.4.2.7 *more* • . . . . • · . • . . • • . . . . . • . . . . . . . . . . . 258<br />

25.4.2.8 Aborts. . ." . . . • • • • • . • . . . . '. . • . . . . . . • . . • . . . . . 258<br />

25.5 Major Modes . . . . • . 0 • 0 • • • • • • • • • 0 • • • • • • • • 0 • 0 •<br />

25.6 Help and Self Documentation • • • . • . . • . . . .. • . • . • . . . . . . . .<br />

258<br />

. 259<br />

25.7 GJossaryofCommands • ..• • • • 0 • 00 0 • • •• 0 • • • • • • • • .260'<br />

25.7.1 Speci<strong>al</strong> Character Commands .... • .... 0 •••••• 0 ••• 0 • 261<br />

261<br />

25.7.2 Contro) CharaclerCommands ... 0 • • • • • • • • • • • • • • • • •<br />

25.7.3 M<strong>et</strong>a Key commands. . . . . . • . . . . • . • • . • • . . . . . . • 264<br />

25.7.4 Control-M<strong>et</strong>a Commands ..•. 0 •• • • • • • • • 0 • • • • • •• 0 266<br />

25.7.5 Control-X Commands. .•. • • · 0 • • • • • •••••••••••••••••• 268<br />

25.7.6 M<strong>et</strong>a-X Commands. . . 0 • • • • • • 0 • • • • • • • • • • • • • • • • • • • • • 271<br />

25.8 Extending the Editor. . • • • • . . • • • • . • . • . • • • • • • . • • • • . . . 0 • • • 274<br />

25.8.1 Editor Functions • 0 • • • • • • • • • • • • • • • • • 0 • • • • 0 • • • • • • • • 0 0 • • 274<br />

25.8.2 Editor Objects • . • • . • • • • • • • • • • • • • • • • 0 • • • • • • • 275<br />

25.8.3 Other Functions and Conventions. 0 • • • • • • • • • • • • • • 0 • 0 • • • • • 277<br />

26. The Patch Facility. • . • • • • • • • • • • • • • . • • • • • 0 • • • • • • • • • • 0 280<br />

26.1 User Functions . . . • • • • • • • • • . . • • • • • 0 • • • • • • • • • 0 • • • • • • • • • 281<br />

26.2 Patch System Infonnation • . . • • 0 • • • • • 0 • • • • • • • • • 0 • 0 • • 0 0 • • 282<br />

26.3 Adding Patches . . . . • • . • • • • • • • 0 • • • • • • • • • 0 • • • • • • • • 282<br />

26.4 Defining Patch Systems. • •• • • • • . • • • • '0 • • • • • • • • • • • • • .284<br />

27. T<strong>al</strong>king to <strong>NIL</strong> •• · • • · • • • • • • · • . • . • • • • • • • • • • • • . • • • . • . . • . 287<br />

27.1 Stanup • • •. • .• • • .• • • • • . • . . • • • • •••..• 0 • 0 • • • 287<br />

27.2 The Toplevel Loop. . • 0 • • • • • • • • • • • • • • • • • • • • • • • • • • 288<br />

27.3 Entering and Exiting <strong>NIL</strong> • . • • • · • • • . . • • • . • . . . . • • •. . . 288<br />

23-DEC-83


-<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

ix<br />

Table of Contents<br />

27.4 VMS .. 0 .. 0 ..•.• 0<br />

27.5 Inst<strong>al</strong>lation . . . . . 0 • • •<br />

27.6 How the <strong>NIL</strong> Control Works<br />

28. Peripher<strong>al</strong> Utilities. . . . .<br />

28.1 The Predicate Simplifier ...<br />

28.2 A Mini-MYCIN. 0 0 ••••<br />

28.3 Mac1isp Compatibility for Macsyma. .<br />

29. Foreign Language Interface ..<br />

29.1 Introduction. . . . . . . . .<br />

29.2 Kernel and System-Services 0<br />

29.3 VMS object files ...<br />

29.4 Data Conversion ..<br />

29.5 lower level routines .<br />

30. What Will Break ....<br />

30.1 What Broke Since Release 0.259. . .<br />

30.2 Future Changes. . 0 • 0 • 0 • 0<br />

30.2.1 Default floating-Point Fonnat .<br />

30.2.2 New Package facility .. 0 0 . 0 •<br />

30.2.3 Vector-push and Vector-push-extend 0 •<br />

30.2.4 Multiple V<strong>al</strong>ues .. 0 • 00 •• 0<br />

30.2.5 Variable Naming Conventions 0 0<br />

,0 ").6 Otlrhaee Col1~ction. .<br />

30.2.7 Error System. 0 •<br />

<strong>Reference</strong>s. 0<br />

Concept Index.<br />

Message Index.<br />

• • 0<br />

Resource Index . 0<br />

Variable and Constant Index. •<br />

Function. Macro. and Speci<strong>al</strong> Fonn Index • • •<br />

• 0 291<br />

0290<br />

o .293<br />

· . 295<br />

· .• 295<br />

• 0 • 296<br />

· .297<br />

· .298<br />

· • 298<br />

· 0298<br />

· .. 299<br />

• 0 299<br />

· . 300<br />

· • 301<br />

. ..... 301<br />

....• 303<br />

· . 303<br />

.303<br />

• 0 303<br />

. 303<br />

· .305<br />

.30S<br />

o 0 305<br />

o 0 307<br />

o 0 0 308<br />

• 0 0 310<br />

· •. 311<br />

o 0 • 312<br />

.•.• 314<br />

23-DEC-83


---------------------------------------------------------------------------------------


<strong>NIL</strong> Manu<strong>al</strong> 1 Introduction<br />

1. Introduction<br />

<strong>NIL</strong>. which stands for New Implementation of Lisp. is a di<strong>al</strong>ect of LISP which runs on the<br />

DEC VAX. <strong>NIL</strong> currently runs under the VMS operating system. It will likely be converted. to run<br />

under U~lX (TM) at some point, but there is no effon underway to do so right now.<br />

<strong>NIL</strong> is a di<strong>al</strong>ect of CO\1MON LIst). COMMOJ\ LISP is essenti<strong>al</strong>ly a form<strong>al</strong> specification of the<br />

LISP language such that programs which confonn to that specification may be transported without<br />

modification from one CO\1\10~ LISP implementation to another, and be expected to run<br />

compatibly. As of this writing. the CO\1\f0~ liSP manu<strong>al</strong> has just gone to press: this manu<strong>al</strong> has<br />

therefore den'loped into documentation of a subs<strong>et</strong> of C()\1\tO~ IISP facilities which are currently<br />

supported by :\11.. and a large number of ~II -specific things.<br />

This document schi/ophrenic<strong>al</strong>l, attempts to cover three areas. One is "primer"<br />

document.ation: those things which must be known for any programming to g<strong>et</strong> done. In this<br />

case. aucmpts arc made to point out what of these things are ('0\1\10:\ LISP compatible. Another<br />

is the s<strong>et</strong> of things which migl;~ he expec-ted to change incompatihl), du£' to (,0\1\10' liSP<br />

conversion. The third is those wllich are part of the :\11 core Virtu<strong>al</strong> lllac/till£'. as it is heing<br />

de\cloped more fonn<strong>al</strong>ly. These include. for example. functions like %string - replace. \\hkh are<br />

sUiLtble low-level primitives for a VAX (or other byte-machine. like perhaps an 1B\1-J70) to<br />

provide. Lastly, there are certain parts of ~IL which have undergone large amounts of recent<br />

development. and are fairly stable. and which· may provide function<strong>al</strong>ity for lIsers in various<br />

domains: the 1/0 system. for example. Much of the pro\'ided documentation will he of things<br />

witidt ,uc ub!'ll:clIciy iuw-ic\'ci: ~omelimes. this is (0 point out piaces where me implementatIon<br />

f<strong>al</strong>ls short of the design: often too. to document these t(lr those who may find it useful,<br />

debugging. or in perfonning implementation-dependent activities: and occasion<strong>al</strong>ly, to explicitly<br />

note how the implementation differs from the gener<strong>al</strong> and portable semantics (as in the case of<br />

numbers and eq).<br />

1.1 Conventions<br />

All otherwise unqu<strong>al</strong>ified ration<strong>al</strong> numbers in this manu<strong>al</strong> are in decim<strong>al</strong>, not oct<strong>al</strong> (as has<br />

been the practice in certain other manu<strong>al</strong>s. notably [9] and [12]). Speci<strong>al</strong> qu<strong>al</strong>ifying syntax for<br />

forcing the interpr<strong>et</strong>ation of ration<strong>al</strong> numbers in other radices is described in section 2.1, page 3.<br />

There are a couple conventions for the fonning names of functions and variables coming into<br />

use from within the COMMON USP community.<br />

Gener<strong>al</strong>ly. variables whose v<strong>al</strong>ues are speci<strong>al</strong> and which may be modified during the course<br />

of program operation have names which begin and end with an asterisk; for instance,<br />

-package-. Lexic<strong>al</strong> variables, and constants defined with defconstant (page 24), are nonn<strong>al</strong>ly<br />

named without these asterisks. For instance, <strong>NIL</strong> defines the constants pi and most-positivedouble-float.<br />

This is a convention only and does not affect the operation of the I'lL interpr<strong>et</strong>er<br />

or compiler; however. the possibility exists tJlat (in tJIC future) the compiler will lISC the presence<br />

or ahsence of such asterisks to choose a course of action if it encounters a free reference to an<br />

undeclared variable. (Speci<strong>al</strong> and lexic<strong>al</strong> variable reference is discussed in chapter 3, page 11.)<br />

MC:NII.MAN:INTRO 18<br />

23-DEC-S3<br />

.<br />

, - ~ -<br />

,"", '.. ' .':: : ~ ..,'-. - ,: -'< c' _ . .'


Cotl\'cnliot1s 2 Nil. Manu<strong>al</strong><br />

'n1e names of predicate functions in!\u, and CO:\fMON LISP are typic<strong>al</strong>ly fi)nned by suffixing<br />

the character t~p" to the end of a descriptive name. For instance.consp is a predicate which is<br />

true if its argument is a cons~ and lessp (which actuaUy is a MACUSP. not COMMON USP.<br />

function) compares numbers and (when given two arguments) r<strong>et</strong>urns t if the first is less than the<br />

second. If the name itself is hyphenated. then "-pit is suffixed: upper-case-p is a predicate<br />

which tells if a character is upper-case. If, however. the predicate name is fonncd by prefixing a<br />

speci<strong>al</strong>izing name to an existing predicate name, then the fin<strong>al</strong> t.p" would not have hyphenation<br />

added to it: string-Iessp is a predicate can be used to compare strings using a standard collating<br />

sequence. the name heing fimned by prefixing "string-" to 'tlessp". There are. of coursc. many<br />

exceptions to this. and this convention does nOl eliminate <strong>al</strong>l ambiguity. but it helps. A goud<br />

numher of ~II functions did not fi)Uow this convention in earlier versiul1sof. ~II: many of these<br />

h~l\'e heen fixed. mld the old names made synonymous with the new names for the time being.<br />

MC:NJLMAN;INTRO 18<br />

23-DFC-83


NIl. Manu<strong>al</strong> 3 I )ata Types<br />

2. Data Types<br />

This chapter provides an overview of some of the data types used in <strong>NIL</strong>. their uses. and<br />

their syntax (their prillted representatio1l). Those not strongly familiar with LISP should go over<br />

this lightly to g<strong>et</strong> some idea of the sorts of objects which <strong>NIL</strong> offers. and proceed to the next<br />

chapter: others might want to read it anyway. to see what <strong>NIL</strong> provides which may differ from<br />

other LISP di<strong>al</strong>ects. Most of the sections here have later chapters devoted to them. which give<br />

much more compl<strong>et</strong>e infonnation on the types. how they may be used. and the functions which<br />

can manipulate them. Also. more compl<strong>et</strong>e 'information on the syntax used for these types is<br />

presented in chapter 20. page 213.<br />

2.1 Numbers<br />

The I'll. (and COM\101' LISP) hierarchy of numeric,l) types looks like this:<br />

number<br />

rationa j<br />

intE:ger<br />

fixnum<br />

bigntJm<br />

ratio<br />

float<br />

short-float<br />

siiigle float<br />

double-float<br />

long-float<br />

complex<br />

Collectively. the non-complex numbers are referred to in <strong>NIL</strong> as the type non-complex-number:<br />

the tenn re<strong>al</strong> is not used because of potenti<strong>al</strong> confusion with floating-point. Note that there is no<br />

guarantee that the above types might not be further subdivided or grouped for the convenience of<br />

the implementation.<br />

2.1.1 Ration<strong>al</strong>s<br />

The integer data type is intended to represent mathematic<strong>al</strong> integers. There is no magnitude<br />

limit on them other than that imposed by memory or addressing limitations.<br />

In <strong>NIL</strong>. those integers which can be fit in a 30 bit field in twos-complement are fixnums.<br />

which are represented in such a way that no storage is consumed. For integers not in this range.<br />

bignums are used. Generic arithm<strong>et</strong>ic functions automatic<strong>al</strong>ly choose the appropriate<br />

representation.<br />

The printed representation of integers ordinarily uses decim<strong>al</strong> notation. option<strong>al</strong>1y preceeded<br />

by a sign character and option<strong>al</strong>ly followed by a decim<strong>al</strong> point. The sharpsign reader macro<br />

(section 20.t page 214) may be used to input ration<strong>al</strong> numbers in other radices; for instance.<br />

MC:<strong>NIL</strong>MAN;TYPES 36<br />

23-DEC-83


Numbers<br />

4 <strong>NIL</strong> MimuaJ<br />

259<br />

259.<br />

#0403<br />

#blOOOOOOl1<br />

; Thc integer 259<br />

; 'Inc integer 259<br />

; entered in {l<strong>et</strong>a!<br />

; entered in binary<br />

A ratio is the type used to represent non-integer ration<strong>al</strong> numbers. It consists logic<strong>al</strong>ly' of<br />

integer components which arc its numer<strong>al</strong>or and drlllJlltillolOr (which arc accessible by functions of<br />

the same names). °rbe exteTmd intcrf,lCc is defined such that a ratio will <strong>al</strong>ways appear to be in<br />

r{'duced fonn (wh<strong>et</strong>her or not it is). and the denominator will <strong>al</strong>w,.ys be positive. (CO\1\10~ I.ISI)<br />

sei'. it can't be I.cro, infinity freaks.) 'nlC ct.rithm<strong>et</strong>ic nmtincs which de<strong>al</strong> with ration<strong>al</strong> numbers<br />

tranpar{,lltly C(}f1\"{'rt b<strong>et</strong>ween r<strong>al</strong>ios. bignums. and fixnumsas aPllfOpria\c. Ratios itrC d{'notcd<br />

separating the numerator and the denominatory by a I: thus. the ratio three-h<strong>al</strong>ves is 3/2.<br />

2.1.2 Floating-point Nunlbers<br />

CO\1MO~ LISP <strong>al</strong>lows for four kinds of floating-point representations, which must me<strong>et</strong> the<br />

filltuwing critcria:<br />

Format ~inimum PreCision Minimum Exponent Size<br />

Short 13 bits 7 bits<br />

Single 24 bits 8 bits<br />

Double 50 bits 8 bits<br />

long 50 bits 8 bits<br />

Nn !lrovid~:111 nf these fnrmat~ with th(' f(ll1(lwing specs:<br />

Type Precision Exponent<br />

short-float 19 bits 8 bits<br />

single-float 24 bits 8 bits<br />

double-float 56 bits 8 bits<br />

long-float 113 bits 15 bits<br />

The long - float type requires microcodc support to avoid software emulation.<br />

Floating-point numbers in <strong>NIL</strong> are syntactic<strong>al</strong>ly distinguished from integers in that they must<br />

have a decim<strong>al</strong> point followed by at least one digit. (This is more rigid than the COMMON USP<br />

specification.) So. for instance, 10 and 10. are both the integer ten. but 10.0 is floating-point 10.<br />

The various fonn<strong>al</strong>s of floating-point number are syntactic<strong>al</strong>ly distinguished by the use of the<br />

character used in exponenti<strong>al</strong> notation. For example. 10.OdO is double-float ten; 10.050 is shortfloat<br />

tcn. 10.010 is long-fioat ten. and 10.0e0 is single-float ten. When exponenti<strong>al</strong> notation is<br />

not used. the type of float is d<strong>et</strong>ermined by the user-modifiable variable .read-default-floatformat.<br />

(page 72). COMMON USP specifics that the default type of float is single-float, both for<br />

readin and the v<strong>al</strong>ues of various irration<strong>al</strong> or tranccndcnt<strong>al</strong> mathematic<strong>al</strong> functions when they are<br />

given ration<strong>al</strong> arguments (c.g.. sqrt). However. in <strong>NIL</strong>. the default is currently double-float,<br />

because this <strong>NIL</strong> release is the first to supply any (onnat other than double-float. The default<br />

;"ill be changed in a future release.<br />

MC:NlI.MAN:TYPES 36<br />

23-()EC-83


Nil. Manu<strong>al</strong> 5 Characters<br />

2.1.3 Complex Numbers<br />

Complex numbers in <strong>NIL</strong> represent a point in the complex plane in cartesian coordinates.<br />

Their printed representation shows these coordinates:<br />

/lC (rea/part imagparg)<br />

The re<strong>al</strong> and imaginary parts may be extracted with the reaipart and imagpart functions.<br />

The re<strong>al</strong> and imaginary components of complex numbers must both be either ration<strong>al</strong><br />

numbers, or floating point numbers of the same floating-point fonnat.<br />

Ration<strong>al</strong> numbers and complex numbers with ration<strong>al</strong> components collecti\"el~ constitute the<br />

gaussian-ration<strong>al</strong> :\11 data typc. Many. but not <strong>al</strong>l. ration<strong>al</strong> number functions ha\'e heen<br />

extended to operate on gaussian ration<strong>al</strong>s in Nil. for instimce numerator. denominator. and<br />

mod. In order to provide what we c<strong>al</strong>l a seamless ex/ellsioll of the ration<strong>al</strong> numbers to the<br />

complex plane. a gaussian ration<strong>al</strong> with a zero imaginary part is not of type complex. but just<br />

the ration<strong>al</strong> number. This interconversion may be compared with that which interconverts b<strong>et</strong>ween<br />

fixnums and bignums a~ necessary. Gaus~ian ration<strong>al</strong>s which have integer components (i.e..<br />

integers. and complex nt.:.,nbers with integer components) are the Nil type gaUSSian-integer.<br />

which is of course a subtype of gaussian-ration<strong>al</strong>. Certain integer flmctions in :'\11. have been<br />

extended to operate on gaussian integers: these include gcd. oddp. and evenp. The gaussian<br />

ration<strong>al</strong> and gaussian integer extensions in 1\11. are not defined by CO\1\10~ l.lS}>. and should<br />

therefore be considered experiment<strong>al</strong> and potenti<strong>al</strong>ly subject to change. For this reason. feedback<br />

on their usage and utility is desired in order tJlat these extensions can be ev<strong>al</strong>uated.<br />

Complex numbers with floating point components <strong>al</strong>ways have components of the same<br />

floating-point format. Such a number is <strong>al</strong>ways of type complex. even if the imaginary part is.<br />

zero.<br />

2.2 Characters<br />

<strong>NIL</strong> provides a data type for representing characters. Characters are the things one<br />

manipulates when doing "character 1/0" on streams. They are the things one g<strong>et</strong>s out of, and<br />

puts into, strings. Having a separate data type <strong>al</strong>lows them to maintain their identity within the<br />

lisp (as opposed to being an interpr<strong>et</strong>ation placed on fixnums, for instance). Chapter 11 is<br />

devoted to this.<br />

Characters in <strong>NIL</strong> use # \ syntax for input and outpu~ as shown below. Note that if the<br />

character after the # \ stands <strong>al</strong>one. it is taken liter<strong>al</strong>ly. If it occurs after a prefix such as<br />

"control- n , then it will be treated like an ordinary token, so may need to have a preceding<br />

backslash to inhibit case translation or just to <strong>al</strong>low proper token parsing.<br />

'\a<br />

: Lowercase "a".<br />

'\A<br />

; Uppercase "a".<br />

'\Control-a<br />

: Uppercase "an, with the control bit.<br />

/I\M<strong>et</strong>a-\a<br />

: Lowercase "a", with the m<strong>et</strong>a bit.<br />

Some characters have names, which may be lIsed in place of the character itself:<br />

/I\Rubout<br />

;'nle "ruhout" or "del<strong>et</strong>e" character<br />

#\Hyper-Space<br />

: The "space" character with the hyper bit<br />

MC:NIl.Mt\N:TYP~S 36<br />

23-DEC-83


Symbols 6 Nil. Manu,,1<br />

Only a subs<strong>et</strong> of <strong>al</strong>l possible characters are a110wcd to be contained in strings. These comprise<br />

the string-char d.tta type. It hClppens that in <strong>NIL</strong> these are tJlose characters which have no font<br />

or· bits attributes (both are 0).<br />

2.3 Symbols<br />

Symbols are what are used as names in lisp_ They can name functions. and variables (the<br />

two uses of which are syntactic<strong>al</strong>1y distinguishable by the . LISP ev<strong>al</strong>uator). Symbols have a 110mI'.<br />

<strong>al</strong>so c<strong>al</strong>led the print /lome or p"ome. which is a string containing the chamcters used in the<br />

printed representation of the symbol. A symbol <strong>al</strong>so has a propert)' lisl or plis! associated with it.<br />

Thi~ is a list of ailefll,lting "indicators" 411ld "\·,tlues". <strong>al</strong>lowing one to sture unidirectiun<strong>al</strong><br />

associations on the symhol. A symhol <strong>al</strong>so has a package. which points to the "name spacc" it is<br />

associated with (chapter IS. page 121)~<br />

The symbol nil is speci<strong>al</strong>. It is used both to represent booleoll folse. and the empty Jist. Its<br />

<strong>al</strong>ternate printed representation is· O. the empty Jist It has the data type null. which is both a<br />

subtype of symbol and a .subt~l)e of list and is the only object of that type. ltli v<strong>al</strong>ue is not<br />

<strong>al</strong>lowed to be changed. OtherwIse. it is lreated the S{.lme as other symbols (it h.1S a property list<br />

<strong>et</strong>c.).<br />

The symbol t is used to represcnt boolean lruth. Its v<strong>al</strong>ue is <strong>al</strong>so not <strong>al</strong>lowed to be changed.<br />

Symbols arc often used as keywords. Because of the existence of multiple namespaces<br />

(packages). t11is might present a problem because two symbols read into different namcspaces<br />

might not be the same. This is solved by haying speci<strong>al</strong> kCYM'(}rd symbols. or just keywords for<br />

short. A symbol which is typed in preceded by a colon (and nothing else) is read into the<br />

namespace (package) for keywords. Thus. an symbols so designated are the same (they are eq).<br />

Keywords are self-ev<strong>al</strong>uating, and their v<strong>al</strong>ues are not <strong>al</strong>lowed to be modjficd~<br />

NotationaUy. tokens which cannot be interpr<strong>et</strong>ed as anything else are taken to be symbols.<br />

except that tokens consisting entirely of unslashified dots are supposed to cause a syntax error~<br />

Thus. , .Oe + 4 will read as a floating-point number. but , .Oe + 4a will read as a symbol. More<br />

compl<strong>et</strong>e d<strong>et</strong>ails on input syntax are in chapter 20. page 213.<br />

2.4 Lists and Conses<br />

A cons is the type which makes LISP what it is. In simpler lisps. it may be the only data<br />

type which can be used to associate more than one object A cons makes a binary association: it<br />

has two components. its car and its cdr, which are accessed by just those functions. It is thus<br />

the datastructure of choice for representing binary trees.<br />

A list. when considered to be a data-type, is the union of the types cons and nutt-that is.<br />

it is either a cons. or the symbol nit (the empty list). That is why the <strong>al</strong>ternate printed<br />

representation of nil is O. (See section 20.1. page 214 for exposition of the printed representations<br />

of cnnses and lists.)<br />

MC:NII.MAN:TYPES 36<br />

23"DEC-83<br />

, " ,;":. i -,~;~;' ,; ',< ,~',<br />

~ "."-<br />

"':<br />

,i "~"~~'~;: co;': -- ," ,',' < :'.,:,,"" ,,' ,•••


-<br />

<strong>NIL</strong> Manu<strong>al</strong> 7 Arrays and Sequences<br />

Often, a list is a conceptu<strong>al</strong> sequence which has a discr<strong>et</strong>e end. In this context. the cdr of<br />

the last cons of the list must be nil. In text (and error messages), the phrase "proper Jist" is<br />

used to distinguish b<strong>et</strong>ween just a cons (or nil) and an actu<strong>al</strong> list whose fin<strong>al</strong> cdr is nil. For<br />

instance. the cons<br />

(a . b)<br />

is of the type list. but if given as a list argument to the member function (page 61) would cause<br />

an error which would say that it was not a proper list.<br />

2.5 Arrays and Sequences<br />

Arrays in 'II. are a ,ery geneml type. One dimension<strong>al</strong> arrays are the type vector. Arrays<br />

can he speci<strong>al</strong>ized as to the types of elemenl'i they may contain. A one dimension<strong>al</strong> array (a<br />

vector) which can only contain "string characters" (see the string-char-p function. page 19) is a<br />

string. A one dimension<strong>al</strong> array which is <strong>al</strong>lowed to hold only objects of type bit (that is. the<br />

integers 0 or 1) is a bit vector. Arrays are discussed fully in chapter 12. page 103.<br />

The type sequence is th;! union of the types list and vector. There are a large number of<br />

Sfl/UfllCf jUllctiollS in 'II. which operate on hoth Jists and vectors, \'iewing either as just a<br />

sequence of ohjects. One therefore has a\'ailahle the same gener<strong>al</strong> sequence operations. to be used<br />

on whatever particular type of datastructure was chosen for the task at hand: they may be lists,<br />

to make adding. delcting. splicing. <strong>et</strong>c.. easy, or \'ectors of a particular type suitable for the<br />

application-strings. bit vectors, <strong>et</strong>c. The functions for operating on sequences are described in<br />

ch:lpter 7, page 4R.<br />

2.6 Structures<br />

<strong>NIL</strong> provides a structure or record definition facility. This is supplied hy the defstruct<br />

function (page 125). which is essenti<strong>al</strong>ly the same one used in both MACLlSP and LISP MACHINE<br />

LJSP. In ~IL. the nonn<strong>al</strong> way defstruct is used defines a type, and the structures creatcd can be<br />

distinguished with typep. Addition<strong>al</strong>ly, such types interface to the <strong>NIL</strong> flavor system, which may<br />

be used to give them m<strong>et</strong>hods for such things as how they should print and pr<strong>et</strong>ty·print<br />

2.7 Functions<br />

There are sever<strong>al</strong> different things which can be "functions" in <strong>NIL</strong>. Most basic<strong>al</strong>ly, there is<br />

the type compiled-function (<strong>al</strong>so known as subr). This corresponds to a function created by the<br />

<strong>NIL</strong> compiler. or part of the <strong>NIL</strong> kernel. It may <strong>al</strong>so be created "on the fly" for the purpose of<br />

interfacing compiled code to interpr<strong>et</strong>ed code; in <strong>NIL</strong>, function<strong>al</strong> ev<strong>al</strong>uation of an interpr<strong>et</strong>ed<br />

function will result in an object of type compiled -function.<br />

Function<strong>al</strong> objects which implement "environment transfer" (which is discussed in a later<br />

chapter) are of the type closure. The most commonly seen speci<strong>al</strong>ization of this type is that used<br />

in the interpr<strong>et</strong>er. the type interpr<strong>et</strong>er-closure.<br />

MC:<strong>NIL</strong>MAN:TYPES 36<br />

23-DEC-83<br />

", - - ' , ',' - " -,' -'" ' '-. ' '-::'. - . ~ , '<br />

'~:~>- -, ',:: .. ':' ' ... -~ '


Random Intern<strong>al</strong> Types 8 <strong>NIL</strong> Manu<strong>al</strong><br />

2.8 Random Intern<strong>al</strong> Types<br />

Here are some of the intern<strong>al</strong>1y used types in <strong>NIL</strong> . While they should gener<strong>al</strong>ly not be seen,<br />

they may pop up on occasion either themselves or as a result of errors.<br />

2.8.1 l\1inisubrs<br />

lbe minisubr type is somewhat gratuitous: it win be flushed as a separate type someday. and<br />

its type bits reused by som<strong>et</strong>hing more uscthl. A millisubr is a speci<strong>al</strong> rOlltine within the 1'11.<br />

k~rnel: Stich routines arc caned with the VAX JSB instn.ctioll. However. they tend to have<br />

various assuned<br />

2.8.2 Modules<br />

A module. as a type. is the structure used by Nil. to contain a collection of compiled<br />

functions and the constants and jat~lstructures they ·reference. When the cumpiler compiles a file.<br />

it produces a module. When the garbagecollcctor (haha) relocates things. it rehlC,ttcs the module<br />

as a hlnck. The use of the name module for this primilhe d<strong>al</strong>Hstnlcture is it bit pr<strong>et</strong>entious .. so it<br />

will probably be c<strong>al</strong>led som<strong>et</strong>hing like compiled-code-modufe in the future.<br />

2.8.3 Intern<strong>al</strong> Markers<br />

The type si:intern<strong>al</strong>-marker is used for variolls things in 1Ioi1L. none of which should<br />

ordinarily be visible to (or touched by) the user. Objects of this type are meant to be checked<br />

for by things like the debugger and garbage-collector (to. for instance. parse stack frames). and<br />

manipulating them out of context wiUconfusc tllese programs.<br />

These objects print out as #!<br />

#fAFM-31<br />

#fPC"MARKI<br />

#!DOUBLE-FLOAT-MARK!<br />

#!NULL-ARGI<br />

followed by the name followed by!. For instance,<br />

; Stack marker for 3-arg function<br />

; c<strong>al</strong>l frame<br />

; Next slot on stack is a PC<br />

: Next two stack entries are the<br />

; representation of a double-float<br />

; Stack slot is for an argument which<br />

has not y<strong>et</strong> been computed,in a<br />

: function caU frame.<br />

MC:Nll.MAN:TYPES 36


<strong>NIL</strong> Manu<strong>al</strong> 9 Coercion<br />

2.8.4 Unused Types<br />

There are a number of unused type codes in <strong>NIL</strong>. Certain intern<strong>al</strong> routines. upon<br />

encountering them. bomb out to the VMS debugger because your <strong>NIL</strong> is then undoubtedly lOSing<br />

its lunch.<br />

2.9 Coercion<br />

coerce o~;ecl Iype<br />

If ol~;ccl<br />

is <strong>al</strong>ready of the type 1),l'e. then it is simply r<strong>et</strong>urned: otherwise, it is COI1\ ened<br />

to be of that type.<br />

Only certain forms uf coercion are defined. coerce wiJI perform coercion of one sequence<br />

type to another: its capabilities in this regard are similar to those of concatenate (page<br />

50). Note. however. that concatenate will <strong>al</strong>ways r<strong>et</strong>urn a copy of the sequence.<br />

whereas coerce will only create a new one if object is not of the proper type <strong>al</strong>ready.<br />

coerce <strong>al</strong>so <strong>al</strong>lows some non-sequence coercion< with the following types:<br />

float<br />

Coerce the object to a floating point number. If object is <strong>al</strong>ready a float, It IS<br />

r<strong>et</strong>urned: otherwise. it is coerced to the default type of float (double-float). See<br />

float. page 78.<br />

short-float<br />

single-float<br />

double-float<br />

long-float<br />

Coerce the object to that particular type of floating point number. Again. this is<br />

similar in function<strong>al</strong>ity to what may be obtained by giving float a second<br />

argument.<br />

complex<br />

object. which must be a number. is coerced to a complex number. If it is<br />

<strong>al</strong>ready complex. it is r<strong>et</strong>urned. If it is ration<strong>al</strong>, it is <strong>al</strong>so r<strong>et</strong>urned; this is<br />

because complex numbers with ration<strong>al</strong> components and a lero imaginary part are<br />

automatic<strong>al</strong>ly reduced to ration<strong>al</strong>s. If, however. it is a floating-point number,<br />

then a complex number with object as its re<strong>al</strong> component and a floating-point zero<br />

of the same fonnat as object as its imaginary component, is r<strong>et</strong>urned.<br />

(complex float)<br />

(complex short-float)<br />

(complex single-float)<br />

(complex double-float)<br />

(complex long-float)<br />

Effectively, these are like coercing the number to complex, and then r<strong>et</strong>urning a<br />

complex number whose re<strong>al</strong>part and imagpart have been coerced to the specified<br />

floating point type.<br />

character .<br />

Conven object to a character. This coercion is only defined for integers (see intchar.<br />

page %). symbols one character long, and vectors whose dement-type is a<br />

subtype of character (i.e., character vectors and strings). Moreover, in the<br />

MC:NII.MAN:TYPES 36<br />

23-DEC-83


Coercion 10 Nil. Manu<strong>al</strong><br />

integer case. an error is sign<strong>al</strong>led if the coercion does not succeed (Le.. int-char<br />

would r<strong>et</strong>urn nil when given the integer abjl'l'I).<br />

Note that coerce docs not providc for cocrcion to ration<strong>al</strong> or integer types. This is<br />

because the issuc of what to do about truncation OT rounding is a· matter of. the intent;<br />

the functions ration<strong>al</strong> (page 78) and ration<strong>al</strong>ize (page 78) may be used to convert<br />

numhers into ration<strong>al</strong> numbers, and the functions floor, ceiling. truncate. and round<br />

(section 10.7, page 79) are useful fix converting both floating-point numbers and ratios to<br />

integers with various sons founding behaviour.<br />

coerce docs not accept .. 11 of the gener~ll fonllsof type that it shuuld: however. must the<br />

simple fOrm<strong>al</strong>s. and cert;linJy &111 tlwse th&l( arc listed clbo\'c. arc handled properly.<br />

When compiled. c<strong>al</strong>ls to coerce with a conswnt second argument arc changed by the<br />

compilcr into c<strong>al</strong>ls to a routinc specific to the task: a few of these, most notably the<br />

conversions to (non-complex) floating p()int, arc handled especi<strong>al</strong>ly efficiently.<br />

Thcre arc a number of nthcr functions which perform specific types of coercions.<br />

instance. string will cocrcca sy~nbol or a string to a string.<br />

For<br />

MC:<strong>NIL</strong>M!\N:TYPES 36<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 11 Scope. Extent, and Binding<br />

3. Scope, Extent, and Binding<br />

The <strong>NIL</strong> interpr<strong>et</strong>er uses lexic<strong>al</strong> seoping. What this means, simply. is that variable references<br />

which are "textu<strong>al</strong>ly within" the code which binds them. are vaHd. Those references which are<br />

not "textu<strong>al</strong>ly within" the binding form are not, and will (typic<strong>al</strong>ly) cause unbound-variable errors.<br />

Consider the definition<br />

(defun make-associations (keys single-v<strong>al</strong>ue)<br />

{mapcar "(lambda (key) (cons key single-v<strong>al</strong>ue» keys»<br />

which takes a list of keys. and r<strong>et</strong>urns an association list associating <strong>al</strong>l of those keys with the<br />

same single v<strong>al</strong>ue (perhaps for usc by assoc). The first argument to mapcar. the lambda<br />

expression. is technic<strong>al</strong>ly a function. (The #' construct is explained hclow.) It is. however.'<br />

textu<strong>al</strong>1y within the binding of the argument Single-v<strong>al</strong>ue. so that variable reference is lexic<strong>al</strong>.<br />

and that function works in Nil. as desired. Consider the <strong>al</strong>ternative form<br />

(defun make-associations (keys single-v<strong>al</strong>ue)<br />

(mapcar ,'make-one-association keys»<br />

(defun make-ane-association (key)<br />

(cons key single-v<strong>al</strong>ue»'<br />

which might appear to be equiva\ ~nt. The reference to single-v<strong>al</strong>ue in the definition of makeone-association<br />

is nol textu<strong>al</strong>ly within the binding of that variable. hence appears "free".<br />

Although this function (in the absence of extra geclarations. as described below) would function<br />

"properly" in the MACLISP or IlSP MACHINE LISP interpr<strong>et</strong>ers. it will not in 1'IL. It is interesting<br />

to note that (again without speci<strong>al</strong> declarative information) both the MACUSP and LISP MACHINE<br />

LISP compilers will treat the second example as an error (or at least produce incorrect code),<br />

because <strong>al</strong>though the interpr<strong>et</strong>ers do not enforce lexic<strong>al</strong> scoping niles, code is compiled that way.<br />

A short note may be in order on the # ' construct which appeared above. # ' is an<br />

abbreviation for (function ...), just as ' is an abbreviation for (quote ...).<br />

In MACI.ISP. the two<br />

are equiv<strong>al</strong>ent. Howe"er. in ~1I. (and to some extent in l.ISP MACHINE I.ISP too), use of this<br />

speci<strong>al</strong> form is necessary to cause the proper (function<strong>al</strong>) interpr<strong>et</strong>ation of the fonn being<br />

ev<strong>al</strong>uated. In fact. in the make-associations example. it is that speci<strong>al</strong> interpr<strong>et</strong>ation which<br />

makes the lexic<strong>al</strong> reference to single-v<strong>al</strong>ue "work". If quote was used instead of function, the<br />

example would not work as desired. function (or # ') need not just be used around lambda<br />

expressions. It may <strong>al</strong>so be used around function names (as in the second make-associations<br />

example). The effect of ev<strong>al</strong>uating (function name) is equiv<strong>al</strong>ent to what the interpr<strong>et</strong>er does<br />

when it "ev<strong>al</strong>uates" name in the function position of a list being ev<strong>al</strong>uated.<br />

<strong>NIL</strong> does not restrict one to using only lexic<strong>al</strong> seoping rules. It is possible to declare to <strong>NIL</strong><br />

that a variable is speci<strong>al</strong>, and should be able to be referenced by code not textu<strong>al</strong>ly within the<br />

binding construct Or. perhaps a variable should have a glob<strong>al</strong> top level v<strong>al</strong>ue and not be bound<br />

anywhere. or maybe even have a top level v<strong>al</strong>ue. and be bound in some places. This is the<br />

purpose of the speci<strong>al</strong> declaration, which <strong>NIL</strong> implements compatibly with COMMON LISP, and<br />

which is about the same as it is in USP MACHINE USP and MACUSP.<br />

Most of the time. speci<strong>al</strong> variables are declared to be speci<strong>al</strong> glob<strong>al</strong>ly. This means that the<br />

<strong>NIL</strong> interpr<strong>et</strong>er (and compiler) will <strong>al</strong>ways treat the variable as being speci<strong>al</strong>. even if there is no<br />

declaration for it at the place it is bound. As a matter of style. variables declared speci<strong>al</strong> are<br />

usu<strong>al</strong>ly given names which begin and end with the character • so that they can be visu<strong>al</strong>ly<br />

MC:<strong>NIL</strong>MAN:BIND 27<br />

23-DEC-83


Scope. Extent. and Hinding 12 Nil. Manu411<br />

distinguished from more "ordinary'· lexic<strong>al</strong>ly scoped variablcs.<br />

variable speci<strong>al</strong> is with defvar (p41ge 24). ror instance.<br />

(defvar -leaves-)<br />

(defun find-<strong>al</strong>I-leaves (tree)<br />

(l<strong>et</strong> (-leaves- nil»<br />

(find-<strong>al</strong>l-leaves-l tree)<br />

-leav.8s-<br />

) )<br />

(defun find-<strong>al</strong>l-leaves-l (tree)<br />

(cond «atom tree)<br />

; Empty sctofleaves<br />

; o rO\lcl over the tree<br />

; And r<strong>et</strong>urn the leaves found<br />

One way to glob<strong>al</strong>ly declare a<br />

(cond «not (memq tree -leaves-»<br />

(s<strong>et</strong>q -leaves- (cons tree -leaves-»»)<br />

(t (find-<strong>al</strong>l-1eaves-! (car tree»<br />

(find-<strong>al</strong>l-leaves-1 (cdr tree»»)<br />

There are more esoteric (or SCIIEMIHike) ways in which the above could have been perfunned.<br />

without the. usc of the speci<strong>al</strong> variable -Ieaves-. but the above is fairly straightforward. fairly<br />

effident. ,md will <strong>al</strong>so run (both k terpreled and -compiled) compatibly in MACUSP and !.lSI'<br />

MACHINE I.ISP.<br />

The above intuitive (or. if you prefer. hand-waving and vague) description can now be used<br />

to more fonn<strong>al</strong>ly define the tenns of scope and extellt which are used to describe the accessibility<br />

and lif<strong>et</strong>imes of things. of which variable bindings are one instance. The scope of som<strong>et</strong>hing tells<br />

where it may be v<strong>al</strong>idly referred to~ To say that som<strong>et</strong>hing has lexic<strong>al</strong> scope then means that it<br />

iHay UC U)CU cJllywiaclc ·'i.cxluaiiy'" within Lhc conSlfUct which "creatcs" the objcct (e.g.. the<br />

lambda-expression which binds a variable). Note that this docs not in itself imply that the<br />

reference becomes inv<strong>al</strong>id if that construct is exited. That dimension is the extelll of the object.<br />

which tens the lime during which the object (e.g.. variable binding) is v<strong>al</strong>id dynamic extent<br />

means that the object (reference) is only vaHd during the execution of the construct. illdefillite<br />

extellt means that there is no such limitation. Variable bindings in the <strong>NIL</strong> interpr<strong>et</strong>er (which are<br />

not speci<strong>al</strong>) have lexic<strong>al</strong> scope and indefinite· extent lbismeans upward funarg capability.<br />

indefinite scope means that there is no restriction on wbere a v<strong>al</strong>id reference may occur from.<br />

This is the case with speci<strong>al</strong> variables; the "free" references may be made from any piece of<br />

code. The bindings of such variables. however, have only dynamic extent; they become inv<strong>al</strong>id<br />

(are "unbound") when the binding construct is exited. This combination of scope and extent,<br />

which is quite common, is· referred to as dYllamic scope.<br />

Now, for the pragmatics. The current <strong>NIL</strong> compiler actu<strong>al</strong>ly only implements loc<strong>al</strong> scope<br />

instead of lexic<strong>al</strong> scope. Its capabilities lie only in dctennining when it is losing. In many cases,<br />

this· docs nOl matter because the constructs being used are expanded out into other construc~<br />

making the references loc<strong>al</strong>. This is what happens for mapcar, for instance: in the construct<br />

(l<strong>et</strong> «22 (computate»)<br />

(mapc #'(lambda (x) (mumblify x 22» some-list})<br />

the reference to zz within the lambda expression is a non-loc<strong>al</strong> (but lexic<strong>al</strong>) reference. That<br />

expression is recoded by the compiJer~ however. as an iteration without a separate function. in<br />

which the reference become loc<strong>al</strong>.<br />

MC:<strong>NIL</strong>MAN:BIND 27<br />

23-DEC-83


N II. Manu<strong>al</strong> 13 I.ambda Application<br />

reference This is actu<strong>al</strong>ly a moderately standard way to handle .lexic<strong>al</strong> variables: rewrite<br />

the f(lnn when possihle to CilUse the reference to become loc<strong>al</strong>. The MACI.lSP compiler<br />

docs this with the mapping functions: even if tJ1e open-code-map switch is turned off, if<br />

such a reference occurs it will expand out the iteration to <strong>al</strong>10w the loc<strong>al</strong> reference.<br />

Environment transfer is implemented with closures. A closure is essenti<strong>al</strong>ly an encapsulation<br />

of a function. and some ponion of a binding environment. The closures with which lexic<strong>al</strong><br />

environment transfer is perfonned in the interpr<strong>et</strong>er. interpr<strong>et</strong>er closures. bundle up the lexic<strong>al</strong><br />

environment as of tJ1e time of their creation. Thus.<br />

(s<strong>et</strong>q fn (l<strong>et</strong> «x 5» (function (lambda () x)})}<br />

=> #<br />

(func<strong>al</strong>1 fn)<br />

=> 5<br />

One may test fln" ~l closure in g.ener<strong>al</strong> with (typep x ·closure). or with the closurep predicate<br />

(page 19).<br />

Nn actu<strong>al</strong>ly has the capability for giving "dvnamic" variables iudefilli/(' extent. '1l1is can be<br />

used to implement old-tashioned closures as creaLj by tJ1e Lisp Machine closure function (which<br />

exists in 1'11.).<br />

In <strong>NIL</strong>. what has been said for variables as far as scope. extend. binding. and shadowing is<br />

concerned. is equ<strong>al</strong>ly true for fUllctions. Variable v<strong>al</strong>ue and function v<strong>al</strong>ue are handled in<br />

virtu<strong>al</strong>ly identic<strong>al</strong> fashions. The primary differences b<strong>et</strong>ween the two are that the interpr<strong>et</strong>er does<br />

new toplc"el specia1 variable v<strong>al</strong>ue when the variable is not glob<strong>al</strong>ly declared speci<strong>al</strong>), and the<br />

compiler makes its speci<strong>al</strong> assumption qui<strong>et</strong>ly.<br />

The design of the ~I1. binding mechanism is described by White in [13].<br />

3.1 Lambda Application<br />

Application of a lambda expression in <strong>NIL</strong> is much like that of LISP MACHINE LISP. A lambda<br />

expression is of the gener<strong>al</strong> fonn<br />

(1 ambda lambda-list {declaration}. {fonn}.)<br />

In the simplest case. lambda-lisl is a (possibly empty) list of variable names, which are the fonn<strong>al</strong><br />

param<strong>et</strong>ers to the lambda expression when it is treated as a function. There must be as many<br />

arguments to the lambda-expression as there are variables. Thus.<br />

«lambda (a b c) (list a be» 1 2 (+ 3 4»<br />

=> (1 2 7)<br />

TIle lambda-list may <strong>al</strong>so contain speci<strong>al</strong> symbols which begin with the character &. These are<br />

·often c<strong>al</strong>led lambda list keywords. but they arc "keywords'· only in the gener<strong>al</strong> sense. i.e.. they<br />

are not typed in with a preceding colon. They are typic<strong>al</strong>ly used to drive the matching of the<br />

fonn<strong>al</strong> param<strong>et</strong>ers (variables) in me lambda list with the v<strong>al</strong>ues they should be bound to. There<br />

are basic<strong>al</strong>ly just four such keywords, each of which is option<strong>al</strong>. and which should appear in the<br />

order they are shown in:<br />

&option<strong>al</strong><br />

'The items from the &option<strong>al</strong> to the next&-keyword (or end of the lambda-list) describe<br />

MC:<strong>NIL</strong>MAN:BIND 27<br />

23-DEC-83


1.4JJl1bda Application 14 <strong>NIL</strong> M4mu<strong>al</strong><br />

option<strong>al</strong> arguments to the function. F..ach such item may be of one of the following<br />

thrms:<br />

variable<br />

)f a corresponding argument is supplied. then variable wi1l be bound to that.<br />

Othcrwisc. it will be bound to nil.<br />

( variable)<br />

Samc as an is01ated variable.<br />

( variable inil-jonll)<br />

If there is a corresponding argument. then l'ariablc is bound to th<strong>al</strong>. If not. then<br />

inil-/iJrm is c"(lluated. and l'ariab/r buund to that result. Thc ev<strong>al</strong>uation of iltiljimJl<br />

is performed in ,til environment where <strong>al</strong>l of the \'4lriHhlcs in the lambda 1ist<br />

to the left of this one have been bound <strong>al</strong>reCldy.<br />

( roriob/(' il1il-}("-1I1 illil-p-"ar)<br />

Just like tJ1C ,previous fnnnat. Addition<strong>al</strong>ly. illit-p" var will be bound to t if there<br />

was an argument supplied. nil if not.<br />

& rest<br />

There must be exactly une item b<strong>et</strong>ween .;t 1 &rest keyword and the next &-keyword (or<br />

the end of the lambda-list). This variable is bound to a list of <strong>al</strong>l the remaining<br />

arguments to the function.<br />

&key<br />

TIle items b<strong>et</strong>ween &key and either &aux or the end of the lambda-list describe<br />

keyworded arguments to the function. "lbese are arguments which are passed by keyword<br />

rather than by position: when given, it must be preceded by the keywurdnaming which<br />

argument it is. The function flU is defined with the lambda list<br />

(sequence item &key (start 0) end)<br />

which means it takes two required arguments (sequence and item). and two keyworded<br />

arguments (slarl and end)_ lbe c<strong>al</strong>ls<br />

(fill sequence new-item :start start :end end)<br />

(fill sequence new-item:end end :start start)<br />

are effectively the same. An keyworded arguments are by default option<strong>al</strong>. The<br />

specification of a key worded argument in the lambda list is nonnaUy the same· as that of<br />

an option<strong>al</strong> argument; thu~ if no :start keyword and associated v<strong>al</strong>ue is specified in a<br />

c<strong>al</strong>l to fjIJ. the Slar! param<strong>et</strong>er defaults to 0, and for elld, the default is nil. The name<br />

of the variable is used to generate the keyword which flags that panicular param<strong>et</strong>er.<br />

AddilionaHy, with the non-atomic fonns of option<strong>al</strong> param<strong>et</strong>er specification. a list of the<br />

actu<strong>al</strong> keyword which should be used and the variable to bind the argument to may be<br />

used instead. For example, if it were desired that the keyword :start be used to flag the<br />

starting index, but that the fonn<strong>al</strong> param<strong>et</strong>er be named i, then the lambda-list could have<br />

been written as<br />

(sequence item &key «:start i) 0) end)<br />

It is important to nOle that if both &key and &rest arc given, then the list the &rest<br />

variable is bound to is the same list from_which the keyworded arguments are extracted.<br />

This is som<strong>et</strong>imes useful if the arguments are going to be passed en-mass to some other<br />

function using apply, or perh4fps to reconstruct the origin<strong>al</strong> arguments to the function in<br />

. order to sign<strong>al</strong> an error.<br />

&aux<br />

Bindings specified with &aux arc for auxiliary variables: they have no correspondence to<br />

the "argumcnts" givcn to the lambda expression. PIne only things which may follow &aux<br />

MC:<strong>NIL</strong>MAN:BIND 27<br />

23-J)EC-83


-<br />

<strong>NIL</strong> Manu<strong>al</strong> 15 Lambd


Prcdic4Jtes 16 Nil. Mamml<br />

4. Predicates<br />

4.1 Type Predicates<br />

4. J.I Type Specifiers<br />

A type specifier is an expression which may be used to exprcs.~ a data-type constraint.<br />

nil No object is of the type nit: nif is a subtype of aU types.<br />

t All objects arc of the type 1. For· instctncc.<br />

(make-array ·(10 10) :.element-type t)<br />

m~tkcs an 10xl0 ~lrmy which can huld objects of any type.<br />

tJt,c-name<br />

This is the most common fhnn of type specifier; just a type name. filr insumcc number.<br />

double-float. string. IJ1'('-llilmemay be .the name of 1 flavor defined with defflavor<br />

(page 173). the name of a stnJcture defined by defstruct {page 125) (assuming defstruct<br />

is not told to implement the stnlcturc in some other fashion). or one of the m,my <strong>NIL</strong><br />

types noted in various places in this document<br />

(not type-specijiery<br />

AU objects which are not of type type-specifier.<br />

Carto !s! !s2 ... IS!?)<br />

The intersection of the types corresponding to the given type spccifiers~<br />

(or lsi Is) •.. tsn)<br />

The union of the types corresponding to the given type sp~jfiers.<br />

(member x) xl ... XIl)<br />

This describes a type which is one of the objects xl, xl, ... xiz. Equ<strong>al</strong>ity is defined by<br />

eql (page 20).<br />

(satisfiesjUnclion-name)<br />

An object is a ttmember" of this type if junction-name r<strong>et</strong>urns a non-null v<strong>al</strong>ue when<br />

applied to it, otherwise it is not.<br />

. There are some more complex fonns which are used variously as synonyms for, and<br />

constraints on. more gener<strong>al</strong> types. For instance:<br />

(integer low high)<br />

An object is of this type if it is an integer b<strong>et</strong>ween low and high. low and high may be<br />

integers. in which case the boundary check is illclusive, lists of integers. in which case the<br />

boundary check is exclusive. or the atom ., which signifies infinity of the appropriate<br />

sign. Thus. (integer 0 .) is a type specifier for <strong>al</strong>l non-negative integers. and (integer<br />

(0) .) or (integer 1 .) for <strong>al</strong>l positive integers.<br />

(signed - byte size)<br />

(unsigned - byte size)<br />

An object is of these types if it can be r.cprcscnted in the appropriate fonn in twos-<br />

MC:<strong>NIL</strong>MAN:PRElJ 29<br />

23-DEC-83<br />

, .. ~ , - ~<br />

-,.:,:c ".,~> .. ); ". }': ..', J'-. : : " ',' ~<br />

,<br />

,.... .' ,". . ~.<br />

,


<strong>NIL</strong> Manua) 17 TYIK' Predicates<br />

complement notation in a field of the specified size. (Without a hidden-bit convention.)<br />

Thus. (signed -byte 3) is the same as (integer -4 3). ,1Ild (unsigned -byte 3) is the<br />

same as (integer 0 7).<br />

bit Either 0 or 1.<br />

(array element-type dimensions)<br />

An object is of this type if it is an array with "the same" clement type and dimensions as<br />

those specified. dimellsions may be the symbol • (or not supplied). which matches an<br />

array of any rank and dimensions. Otherwise. it should he a list: it then matches an<br />

array \vhose rank is the length of the list. The clements of the list may be either the<br />

symhol *. or a non-negative integer which is the size of the corresponding dimension.<br />

For instance. the dimensions Jist (3 4 5) refers to a 3x4x5 array, ,md (3 • 5) an array<br />

whose first dimension is 3., second is of any size. and third is 5.<br />

There arc two different contexts the type specifier can be used in. and they affect the<br />

interpr<strong>et</strong>ation of the eJemeIlJ-t)1Je. These arc<br />

declaratioll<br />

in which som<strong>et</strong>hing is being declared to take on v<strong>al</strong>ues of this ty)e (declarations<br />

arc discussed in chapter 6). What the type specifier says is that the type is the<br />

same as would be r<strong>et</strong>urned by make-array were it given an clement-type of<br />

element-type and dimensions conforming to dimensions.<br />

discrimination<br />

which is re<strong>al</strong>ly JUSt usc of the type specifier as a second argument to typep. In<br />

t,;is ,,,:;e, the questk,n being dskeJ is w'hcthcf i,he ubjed tJ\.:illg h:~ico i~ uf e.xac/iy<br />

this type.<br />

These two "questions" arc different because of the way make-array (page 103) interpr<strong>et</strong>s<br />

its element-type argument. which is fully discussed in section 12.2. page 104. Basic<strong>al</strong>ly.<br />

what you g<strong>et</strong> from make-array is an array whose clement-type is the closest speci<strong>al</strong>ization<br />

to the specified element-type which make-array can provide.<br />

Fin<strong>al</strong>ly. the elemelll-type can be *, which means any element type at <strong>al</strong>l. Thus, (array t<br />

dims) is a not a subtype of (array • dims). because the former only refers to arrays<br />

which can hold clements of any type, whereas the latter includes bit arrays, string-char<br />

arrays, <strong>et</strong>c.<br />

(simple-array elemel1l-typ~ dimensions)<br />

This is like (array element-type dimensions). but addition<strong>al</strong>ly states that the array has been<br />

created without any "fancy options"; see chapter 12, page 103.<br />

(vector elemenl-t}pe size)<br />

This is equiv<strong>al</strong>ent to (array element-type (size».<br />

MC:<strong>NIL</strong>MAN:PRED 29<br />

23-DEC-83


Type Predicates 18 <strong>NIL</strong> Mcamwl<br />

4.1.2 Gener<strong>al</strong> Type Predicates<br />

typep objecl &option<strong>al</strong> type-specifier<br />

If only one argument is supplied. this is (somewhat) like MACl.ISP typep, and r<strong>et</strong>urns the<br />

exact implementation type of object. In NIl.. this is usu<strong>al</strong>ly som<strong>et</strong>hing too specific to be<br />

worth looking at<br />

Otherwise. r<strong>et</strong>urns t jf object is of type type-specifier, nil otherwise. See thc description of<br />

type specifiers. abovc.<br />

sub typep (l1)l'-Spcc(fin'"' (l'l'l'-Spccijir,... 2<br />

subtypep attempts lo dClcnnine if I)1J('-sp('cijier-r is a subtype of ~l·l'c-spl'(·ijier-2. It<br />

r<strong>et</strong>urns two \'4tlues~ the sC(,(Jlld will he t if thc rchllion could h(' d<strong>et</strong>ermined. nil if il could<br />

not he. Thc first is t if the rehltion can be d<strong>et</strong>ermined and 1J'1'c-.VJccilier-' is in fil<strong>et</strong> a<br />

subtype of 1)1U'-lPCCijicr-2. nil otherwisc.<br />

In \,lL if the type spccifiers are atomic type names and Iype-spccijie,../ j'.: a subtype of<br />

I),}}('-specilier-l. then subtypep will probably succeed in d<strong>et</strong>ermining this. ~,I t),pc-spcdjie,..<br />

/ is 1101 41 subtype of I)'pr-spcdjicr-2. then subtypep may fail to be able to d<strong>et</strong>cmline the<br />

relation. because it may not know that panicular supcrtypcs are mutu<strong>al</strong>ly exclusive.<br />

For instance.<br />

(subtypep 'fixnum 'number) => {t. t}<br />

(subtypep 'character 'number) => {nil! t}<br />

(subtypep 'number 'fixnum) => {nil, t}<br />

(subtypep '(satisfies fixnump) 'number) => {nil. nil}<br />

4.1.3 Specific Type Predicates<br />

null object<br />

This r<strong>et</strong>urns t if object is nil. nil otherwise. Stylistic<strong>al</strong>ly. null is used to test for object<br />

being the· cmpty list, whereas not (page 28), which is function<strong>al</strong>Jy equiv<strong>al</strong>ent because of<br />

the empty-listlboo)ean-faJse du<strong>al</strong>ity of nif, is used to test for boolean f<strong>al</strong>seness. This is<br />

why constructs of thc fonn<br />

(i f (not (null x) 1 frob-non-nul/-x frob-null-x)<br />

are so prcv<strong>al</strong>ent.<br />

symbo lp object<br />

R<strong>et</strong>urns t if object is a symbol, nil otherwise.<br />

consp object<br />

R<strong>et</strong>urns t if object is a cons, nil otherwise. This is the same as (not (atom object».<br />

11 stp. object<br />

consp or nult<br />

MC:<strong>NIL</strong>MAN:PRED 29<br />

23-f)EC-83


<strong>NIL</strong> Manu<strong>al</strong><br />

19<br />

Type Predicates<br />

f1xnump object<br />

characterp object<br />

These test for the exact types fixnum and character.<br />

str1ng-char-p character<br />

Tells if character is a character which may be stored in a string. 'Ibis wiJ] be a type of<br />

sorts in COMMON LISP, such that a string is a vector with clements of type string -char.<br />

Note that string-char-p requires its argument to be a character. as opposed to just any<br />

object: it is not re<strong>al</strong>ly a gener<strong>al</strong> type prcdicate~<br />

In 'II., this is characters with bill' and fiJI/I of 0 (sec chapter 11).<br />

str1ngp object<br />

vectorp oNect<br />

Tell if ubject is a string or vector respectively.<br />

O~;(,CI 'string) and. (typep object 'vector).<br />

These arc equiv<strong>al</strong>ent to doing (typep<br />

numberp object<br />

f10atp object<br />

These are the same as (typep object 'number) and (typep object 'float) respectively.<br />

closurep object<br />

Tells if object is a closure.<br />

The following are supported for MACUSP compatibility:<br />

pa 1 rp object<br />

lbis is synonymous with consp. Once upon a time. the name for cons in <strong>NIL</strong> was pair,<br />

and the function pairp was inst<strong>al</strong>led in MAC1JSP. Now, <strong>NIL</strong> and COMMON US}> c<strong>al</strong>l a cons<br />

a cons.<br />

b1gp object<br />

(typep object 'bignum)<br />

11xp object<br />

Equiv<strong>al</strong>ent to integerp. i.e.. (typep object 'integer). This name should be avoided<br />

because of possible confusion with fixnump.<br />

flonump object<br />

This is the same as (typep object 'double-float). for historic<strong>al</strong> reasons, not the same as<br />

ffoatp. It is provided for MACLISP compatibility only.<br />

MC:NlI.MAN:PRPD 29<br />

23-DEC-83


EqlWfilY Predicates 20 Nil. Manu<strong>al</strong><br />

4.2 Equ<strong>al</strong>ity Predicates<br />

Note <strong>al</strong>so null (page 18) and not (page 28). for testing for nil.<br />

eq x y<br />

'Ibis tens jf x and J' are the exact same opjcct. Implemcntation<strong>al</strong>ly, this is truc if x and y<br />

arc the same "pointer". For instance.<br />

(s<strong>et</strong>q -foo-(con5 'a 'b» => (a. b)<br />

(eq -foo•• foo*) => t<br />

(s<strong>et</strong>q *bar- (cons 'a 'b» => (a. b)<br />

(eq -foo* -bar*) => nil<br />

Philosophic<strong>al</strong>ly. what this predic.lle S


<strong>NIL</strong> Manu<strong>al</strong> 21 Equ<strong>al</strong>ity Predicates<br />

equ<strong>al</strong>p x y<br />

This is a more "gener<strong>al</strong>" version of equ<strong>al</strong>. Numbers are considered to he equ<strong>al</strong>p if they<br />

are numeric<strong>al</strong>ly equ<strong>al</strong>; type conversion wil1 OCCllr if needed to pcrfonn the comparison<br />

(see =. pagc 73). Charactcrs are compared with char-equ<strong>al</strong> (page 95). so are considercd<br />

equ<strong>al</strong>p cven jf thcy differ in casco Conses arc equ<strong>al</strong>p if their respective cars and cdrs<br />

are equ<strong>al</strong>p. Arrays arc equafp jf they have the same rank and dimensions. and if their<br />

corrcsponding clemcnts are equ<strong>al</strong>p: thus. a string will be equ<strong>al</strong>p to a gcner<strong>al</strong> vector<br />

containing equ<strong>al</strong>p characters:<br />

(equ<strong>al</strong>p #(#\F #\0 #\0) "foO") => t<br />

equ<strong>al</strong>p. likc equ<strong>al</strong>. is imp1cmcnled reclIrsi\cly so may dk' on circu1ar structures.<br />

MC:<strong>NIL</strong>MAN:PRED 29<br />

23-DEC-83<br />

, ,. ", ',' ,'" ,:" • O'" ' ',,', :, ,': ',' ,: . " ' , '<br />

-, -<br />

--' '".; .;-.. ' :~~'~~:-. "',~:'".' ---,.'., ~,:, -: ;': ,-, - " '..:- .', -, ' ,


Programming Constructs 22 <strong>NIL</strong> Manu<strong>al</strong><br />

5. Progr<strong>al</strong>nnling Constructs<br />

The <strong>NIL</strong> speci<strong>al</strong> and top)evel fonns.<br />

5.1 Compositions<br />

progn {{onn}-<br />

progn ev<strong>al</strong>uates each of the fhnns~ and r<strong>et</strong>urns the v<strong>al</strong>ue of the last. It is. therefore. a<br />

way· (0 g<strong>et</strong> multiple expressions in a position where only one is caUedfhr.<br />

(progn) nil<br />

(progn jiJnll) jiJnl1<br />

and<br />

( pro 9 n fo n,,·/ jiJnn-2 .•. jiJnl1-11 )<br />

ev<strong>al</strong>uates ,111 of the fontls. r<strong>et</strong>urning the result of the ev<strong>al</strong>uation of [onn-n.<br />

Back in the olden days of LISP. mc.my ~peci<strong>al</strong> foons only <strong>al</strong>lowed a single expression<br />

where we now <strong>al</strong>low multiple expressions to be cv<strong>al</strong>uatcd in sequence; for instrlflce. in the<br />

consequent') of the cond speci<strong>al</strong> form (page 28). This often necessitated tJleexplicit lise<br />

of the progn speci<strong>al</strong> fonn in such places. and is where the tenn implicil prugll. which<br />

describes a situation where such multiple forms are <strong>al</strong>lowed. comes from.<br />

prog1 first-fonn {{onn}·<br />

prog1 ~v:lln;ltC'C\ fir'i/-fnrm. (\nd s~ve~ tht:' v~'lJe: then it cv<strong>al</strong>uat~ an of t.~e other fcrm~.<br />

but instcad of rcturning the v<strong>al</strong>ue of the last like progn docs. it r<strong>et</strong>urns the v<strong>al</strong>ue saved<br />

from the the ev<strong>al</strong>uation of jirst-[onll.<br />

prog2 first-Jonn second-fonn (tOmt)­<br />

This is entirely equiv<strong>al</strong>ent (0<br />

( pro 9 n firsi-fonn (p r 0 9 1 second-fonn fonn. •• »<br />

In other words, it ev<strong>al</strong>uates <strong>al</strong>l of the fonns in order, and r<strong>et</strong>urns the v<strong>al</strong>ue (it saved) of<br />

the second.<br />

5.2 Definition Forms<br />

5.2.1 Defining Functions<br />

defun name lambda-list {declaration}- [documentatioll] {fOnn}-<br />

Defines name as a function, equiv<strong>al</strong>ent to a lambda expression formed using the lambda<br />

IisL declarations. and forms.<br />

For MACLJSP-Compatibility, the following idiosyncratic syntaxes are recognized speci<strong>al</strong>ly:<br />

(I) If lambda-lisl is the atom macro, then this is assumed to be a MACI.lsp-style<br />

macro definition. and is transfonned appropriately.<br />

(2) If lambdwlisl is a non-nuH atom, then this is considered to be a MACLISP lexpr<br />

definition. name will be defined as a function of a variable number of arguments,<br />

MC: N II.M /\ N: pca NS 81<br />

2J~DEC-83<br />

. '<br />

:,::': ,":_:.:"0·;~;\. '.- .. -:,;:;>.t:~:;.~c~.,;


Nil. Manu<strong>al</strong> 23 Dc·finilion Fonns<br />

and the symhol lambda-list hound to that number. The functions arg and s<strong>et</strong>arg<br />

may then he used (compatibly with MACI.ISP) to access the arguments.<br />

(3) If lambda-list is the atom fexpr. then this is assumed to be a MACLlsp-style fexpr<br />

definition. and an attempt is made to turn it into a Nil, speci<strong>al</strong> fonn. Note. of<br />

course. that due to ev<strong>al</strong>uator semantics this will usu<strong>al</strong>ly not work (caBs to. ev<strong>al</strong><br />

will. for instance. utilize a new lexic<strong>al</strong> contour).<br />

In principle. name is a gener<strong>al</strong> function specifier ("function-spcc") as is done in LISP<br />

MACIII'F IISP. However. these hm'c not been put into ~I1. y<strong>et</strong>. so one addition<strong>al</strong><br />

idiosyncratic syntax (<strong>al</strong>so MACI.ISP compatible) is recognized: lI<strong>al</strong>llC may be a list of the<br />

form (namc I'ropl1amc). in which case the function is placed on the propn(]mc properly of<br />

namc. That is. one can do som<strong>et</strong>hing like<br />

(defun (faa hack) (x y)<br />

(list (* (sinh x) (cos y» (* (cosh x) (sin y»»<br />

with the result that<br />

{func<strong>al</strong>l. (g<strong>et</strong> 'foo 'hack) x y)<br />

will invoke a compiled function to perfonn that computation.<br />

5.2.2 Defining l\lacros<br />

A LISP macro differs from an ordinary function in that the code of the macro is run, not' to<br />

obtain a v<strong>al</strong>ue for the fonn. but rather to obtain a new fonn to be used in place of the origin<strong>al</strong><br />

form. 1n 'lSP. thiC\ iC\ nnt (innp thr(lneh ~ny stf!mz~ and miracu101..!s string-processing and<br />

substitution. but by USP code itself: LISP program code is just LISP data. which can be<br />

manipulated and constructed by ordinary LISP programs. When a macro c<strong>al</strong>l is encountered by a<br />

USP compiler. the code for the macro is run then and there. during the compilation. to construct<br />

the new fonn which must be compiled instead. For that reason. LISP macros. while gener<strong>al</strong> LISP<br />

functions, should not depend on their dynamic environment (<strong>al</strong>though if properly arranged they<br />

may have glob<strong>al</strong> declarative or definition<strong>al</strong> information around).<br />

defmacro name pattenl {declarations}* {documentation}- Yonn}*<br />

This is the preferred way for macros to be defined. name is defined as a macro. When a<br />

c<strong>al</strong>l to name is encountered by the interpr<strong>et</strong>er or compiler, the list of arguments to name<br />

(specific<strong>al</strong>ly, the cdr of the c<strong>al</strong>ling form) is matched against p<strong>al</strong>tern; the fonns are then<br />

ev<strong>al</strong>uated in an environment where the variables specified by p<strong>al</strong>lern are bound to the<br />

components of the arguments which they match. and the resulting v<strong>al</strong>ue is used in place<br />

of the origin<strong>al</strong> fonn.<br />

p<strong>al</strong>lem is gener<strong>al</strong>1y a pattern of symbols and conses. but it may <strong>al</strong>so have in it,<br />

intennixed, &option<strong>al</strong>. & rest. and &body. (&body is treated just like &rest by<br />

defmacro pattern matching. However, it is supposed to be an indication to a code<br />

fonnatter (pr<strong>et</strong>ty-printer. or an editor) that the following forms are a "body" rather than<br />

just a sequence of more arguments.) The following defines foo as a macro to be<br />

synonymous with car:<br />

(defmacro foo (x)<br />

( 1 is t • car x»<br />

In <strong>NIL</strong>. the &mumble keywords need not be "top-level" within the pattern:<br />

MC:<strong>NIL</strong>MAN:PCONS 81<br />

23-DEC-83


I xfinition Fonns 24<br />

(defmacro with-output-to-string «var &option<strong>al</strong> string).<br />

&body form)<br />

... )<br />

Especi<strong>al</strong>ly useful fhr constnlcting code in the bodies of macros is the backquote reader<br />

macro. section 20.1.1. page 216.<br />

Eventu<strong>al</strong>ly. defmacro will be extcnded to support these addition<strong>al</strong> Jambda-list keywords:<br />

&key kcyspecl keyspec2 ...<br />

Pr<strong>et</strong>ty much like the ordinary lISC of &key in lmnhd,. lists (section 3.1. page 13).<br />

&whole l'l.1riablc<br />

Binds l'lIri41b/(' to the ma


<strong>NIL</strong> Manu<strong>al</strong> 25 Binding and Assignment<br />

5.2.4 Controlling Ev<strong>al</strong>uation Time<br />

Macros often need to r<strong>et</strong>urn multiple fonns to be processed as if they <strong>al</strong>l appeared<br />

independently at lOplevel. For instance. defvar and its variants could <strong>al</strong>l be trivi<strong>al</strong>ly implemented<br />

as macros (if they aren't <strong>al</strong>ready). In 1'11.. they may be r<strong>et</strong>urned within a progn speci<strong>al</strong> fonn.<br />

For instance. a simplified defparam<strong>et</strong>er, which did not handle documentation, could have- been<br />

written like this:<br />

(defmacro defparam<strong>et</strong>er (variable v<strong>al</strong>ue-form)<br />

t(progn (proclaim '(speci<strong>al</strong> ,variable»<br />

(s<strong>et</strong>q .variable .v<strong>al</strong>ue-form»)<br />

proclaim and declarations are described in chapler 6. p,lge 41. The \1:\( 'liSP hack where the first<br />

clement of the progn had to be the fllnn (quote compile) is not needed (but will work just fine).<br />

This behaviour and the speci<strong>al</strong> casing only applies to toplevel fonns.<br />

ev 81 -when kwd-list lfonn}"<br />

This is as if each of the forms appe~red at topleve1. but were only there to be processed<br />

at the times specified by kwd·/isl. The <strong>al</strong>lowable keywords for kwd-list are<br />

ev<strong>al</strong><br />

When the ev<strong>al</strong>-when fonn is ev<strong>al</strong>uated by the interpr<strong>et</strong>er.<br />

load<br />

When the forms of the ev<strong>al</strong>-whenare loaded compiled (they will be treated as if<br />

th~y were:- ~l?l?n at top!eve! by the compiler; c.g., defuns wi!! b~ cmnpH~d. ~tc.).<br />

compile<br />

The jonns will be ev<strong>al</strong>uated immediately when processed by the compiler. Note<br />

that ev<strong>al</strong>-when keywords arc 1101 symbols in the keyword package (that is, you<br />

don't type them in with a colon in front).<br />

Note that for historic<strong>al</strong> reasons, these "keywords" are only keywords in the gener<strong>al</strong><br />

sense-they are not symbols in the keyword package (typed in with a colon prefix).<br />

5.3 Binding and Assignment<br />

s<strong>et</strong>q {variable v<strong>al</strong>ue}-<br />

s<strong>et</strong>q changes the v<strong>al</strong>ues of variables.<br />

(s<strong>et</strong>q a (f) b (g»<br />

makes the v<strong>al</strong>ue of a be the result of ev<strong>al</strong>uating (t), then makes the v<strong>al</strong>ue of b be the<br />

result of ev<strong>al</strong>uating (9). The v<strong>al</strong>ue r<strong>et</strong>urned by s<strong>et</strong>q is the last v<strong>al</strong>ue stored/computed,<br />

which in this case is what b now will ev<strong>al</strong>uate to, and what (9) ev<strong>al</strong>uated to.<br />

The choice of wh<strong>et</strong>her to change the lexic<strong>al</strong> or dynamic v<strong>al</strong>ue of the variable which s<strong>et</strong>q<br />

makes is the same as that which would be made by the ev<strong>al</strong>uator in ev<strong>al</strong>uating the<br />

variable; and if there is no binding of the variable. s<strong>et</strong>q creates a glob<strong>al</strong> dynamic v<strong>al</strong>ue<br />

for it.<br />

MC:<strong>NIL</strong>MAN:PCONS 81<br />

23-DEC-83


Binding and ;\ssignment 26 Nil. Manued<br />

ps<strong>et</strong>q {variable v<strong>al</strong>ue}-<br />

ps<strong>et</strong>q is syntactic<strong>al</strong>ly like s<strong>et</strong>Q. but it updates the variables in par<strong>al</strong>lel. That is. an of the<br />

v<strong>al</strong>ues are computed. before any of the variables are side-effected. A common idiom<br />

which uses this is<br />

(ps<strong>et</strong>q x y y x)<br />

which exchanges the v<strong>al</strong>ues of x and y. .<br />

ps<strong>et</strong>Q <strong>al</strong>ways r<strong>et</strong>urns nil.<br />

l<strong>et</strong> ({\'{lriab/e v<strong>al</strong>ue}' {declaratiull}- {/bn,,}-<br />

l<strong>et</strong> ev<strong>al</strong>u<strong>al</strong>es <strong>al</strong>l of the nilu('s. and then binds illJ of the l'ariablr ., to the corresponding<br />

v<strong>al</strong>llc~. ;\11 of the "<strong>al</strong>ues arc cumputed b<strong>et</strong>l)re any of the bindings are perf(lIlned.<br />

(l<strong>et</strong> «a (f». (b (g)))<br />

funns. .. )<br />

ev<strong>al</strong>u3t.es (f) and (g), then binds a to the result from the ev<strong>al</strong>uation of (fl and bto the<br />

result of the ey<strong>al</strong>uation of (g). and then ev<strong>al</strong>uates <strong>al</strong>l of the forms: the v<strong>al</strong>ue of the last<br />

fimn is r<strong>et</strong>urned ,IS the v<strong>al</strong>ue of the l<strong>et</strong>.<br />

Various other constructs in ~I1. accept a list of lists of variables and v<strong>al</strong>ues syntactic<strong>al</strong>ly<br />

the same as that used by l<strong>et</strong>. This is Wh,lt is meant by the tenn lel/isl.<br />

In NIl.. l<strong>et</strong> will accept in place of a variable. a pattern used for deslTUc/urillg. The<br />

variables within the pattern arc bound to thc corresponding parte; of the v<strong>al</strong>ue. This is<br />

"imil~r to thp iJ'lf('rf.'l(,C' t(l d~strlJc!t!nng used by d~fmacro: see it. page :n. for mere<br />

infonnation on this pattcm·directed deslfucturing.<br />

Because COMMON US}> l<strong>et</strong> is not defined to suppon destructuring. it· is recommended that,<br />

if destructuring is used. it be hidden in a macro. This will make it both easier to read<br />

(an tllC extra parentheses needed to use l<strong>et</strong> with deslfucluring make it hard to read), and<br />

<strong>al</strong>so make it easier to change should l<strong>et</strong> eventu<strong>al</strong>ly be changed to 110/ support<br />

destructuring (at which time there will be a primitive provided which docs). For instancc 9<br />

the !"IL compiler defines the macro debind-args to destructure argument lists of fonns<br />

being compiled:<br />

(defmacro debind-args (arglist-pattern form &body body)<br />

-{l<strong>et</strong> «.arglist-pattern (cdr ,form») ,8body»<br />

Eventu<strong>al</strong>ly <strong>NIL</strong> will provide some speci<strong>al</strong> fonns and functions for g<strong>et</strong>ting at the<br />

destructuring and argument· list matching function<strong>al</strong>ity provided by defmacro.<br />

l<strong>et</strong>. ({(variable v<strong>al</strong>ue)}' {dec/or<strong>al</strong>ion}- {{onn}-<br />

Syntactic<strong>al</strong>1y, l<strong>et</strong>. is similar to J<strong>et</strong>. However. rather than binding the variables in par<strong>al</strong>lel.<br />

it binds them sequCllli<strong>al</strong>ly. That is. when each v<strong>al</strong>ue fonn is ev<strong>al</strong>uated. the corresponding<br />

variable is bound to that v<strong>al</strong>ue, and the following v<strong>al</strong>ues are ev<strong>al</strong>uated in that<br />

environment. For instance,<br />

(1 <strong>et</strong>. « a jomlJ) (b fonn2»<br />

compute}<br />

first ev<strong>al</strong>uates fonnl. and binds a to that v<strong>al</strong>ue. Then. it ev<strong>al</strong>uates jOnn2, and binds b<br />

,to thaI v<strong>al</strong>ue. Fin<strong>al</strong>ly. it ev<strong>al</strong>uates compute and r<strong>et</strong>urns that v<strong>al</strong>ue as the v<strong>al</strong>ue of the<br />

l<strong>et</strong>·.<br />

MC:NJI.M;\N:PCONS 81<br />

23-DEC-83


Nil" Manu<strong>al</strong> 27 Binding and Assignment<br />

5.3.1 DynamicaHy Binding Variable Variables<br />

The routines in this section may be used to bind variables which are not known at codewriting<br />

(or compile) time. They <strong>al</strong>l bind the speci<strong>al</strong> (dynamic) v<strong>al</strong>ue of the variable.<br />

There are four variations on how the variables may be bound. Which is used is a matter of<br />

which is best suited for the particular task at hand. Basic<strong>al</strong>ly, the variations <strong>al</strong>l involve how the<br />

v<strong>al</strong>ue is computed.<br />

progv varlis, v<strong>al</strong>lis, fonns ...<br />

progv binds each of the ,"ariahles in \,o"'is/ to the corresponding "<strong>al</strong>lies in r<strong>al</strong>lis'. If there<br />

arc too many v<strong>al</strong>ues in ml/isl. the extras are ignored. If there are too Icw. then the<br />

extra variables will he bound "unbound". P.ach of the forms is then ev<strong>al</strong>uated in an<br />

environment in which the variables arc so bound: they arc <strong>al</strong>l bound dynamic<strong>al</strong>ly.<br />

progv is defined by (,OM~10N-I.ISP.<br />

None of the following spechtl fmms are, however.<br />

The following three spedaJ fonns an take an a-list as a specification of what variables to bind<br />

to what v<strong>al</strong>ues. The car of each entry in the a-list is the variable to be bound. I f the 'cdr is nil<br />

(the entry has a length of 1). then the variable will be bound "unbound". Otherwise. tJle cadr<br />

(110/ the cdr) of the entry tens what v<strong>al</strong>ue the variable should be bound to: the exact<br />

interpr<strong>et</strong>ation varies with the speci<strong>al</strong> fonn in use. In <strong>al</strong>l cases. the bindings are pcrfonned<br />

sequenti<strong>al</strong>ly: each variable is bound to its v<strong>al</strong>ue before the v<strong>al</strong>ue for the next variable to be<br />

bound is d<strong>et</strong>cnnined.<br />

progw a-IiSl funns ...<br />

The second clement of each entry in a-list is a fonn to ev<strong>al</strong> to g<strong>et</strong> the v<strong>al</strong>ue to bind the<br />

variable to.<br />

progwq a-list fonns .••<br />

This is son of a trivi<strong>al</strong> speci<strong>al</strong>-case of progw. The second clement of each entry in a-lis/<br />

is the actu<strong>al</strong> v<strong>al</strong>ue to bind the variable to; no ev<strong>al</strong>uation is perfonned.<br />

progw1 a-list forms ...<br />

This junction may lIot y<strong>et</strong> be ill the existing <strong>NIL</strong>.<br />

This is a variant of progw more in keeping with a LISP implementation in which things<br />

g<strong>et</strong> compiled. The second element of each entry in a-list is a function to be c<strong>al</strong>led on no<br />

arguments to d<strong>et</strong>ennine the v<strong>al</strong>ue to bind the variable to. This is much more practic<strong>al</strong><br />

than progw because it can eliminate a lot of interpr<strong>et</strong>er overhead.<br />

The typic<strong>al</strong> use of these speci<strong>al</strong> fonns is to provide a dynamic environment. the specification<br />

"of which may be augmented modularly, and hence might not be tot<strong>al</strong>ly known to the writer of<br />

the code which pcrfonns the binding. progw and its variants are usu<strong>al</strong>ly more convenient for this<br />

purpose than progv. because the specification of the environment is in a single datastructure.<br />

which might be kept around as the v<strong>al</strong>ue of a variable. Note however that progw. progwQ. and<br />

progwf are /lui defined by COMMO:"'-liSP. progw is defined by LISP MA(,II(~E LISP, but progwQ<br />

and progwf are not.<br />

~1C:<strong>NIL</strong>MAN:PCONS 81<br />

23-DEC-83


Condition<strong>al</strong>s 28 Nil. Manued<br />

5.4 Condition<strong>al</strong>s<br />

1 f predicate cOllsequel1l [else/omlJ<br />

not x<br />

if ev<strong>al</strong>uates predicate. If the result is not f<strong>al</strong>se (i.e.. nO( nil). then the result of the if is<br />

the rcsult of ev<strong>al</strong>uating cOlJsequent. Otherwisc. jf· else/onn is specified. the result of thc if<br />

is the result ofevaJuating else/onn. otherwise nil.<br />

not is used )ogic<strong>al</strong>1y (0 invert the scnsc. of a predicatc. That is. it is byconvCnlion used<br />

to test for the object representing boo/ran jill.')£'. Because of the emply-list/booJean-faJse<br />

du<strong>al</strong>ity of the symhol nit. iris function<strong>al</strong>ly equhHlcnt to nuft (page 18). which logic<strong>al</strong>ly<br />

checks fbr the CIIII'I)' /isl which is represented by thc type named nult Thus. one ottcn<br />

sees c()nstruct~ of the thml<br />

( i f (n 0 t (n u 1·1 1» ('()f1scqU(,111 r/sejiJn1l)<br />

because nuff is used to check for empty-listness (fbr instance. being m the end of an<br />

iter<strong>al</strong>iun down a list). and the not is used to invert the sense. so that the cOllsequcllt will<br />

be nm if there is in facl som<strong>et</strong>hing left to the list l.<br />

cond {(prctiicllir {collsequent}-»-<br />

GenemJ historic<strong>al</strong> condo Each predic<strong>al</strong>r to the cond is ev<strong>al</strong>uated. in order. If the result<br />

of an ev<strong>al</strong>uation is f<strong>al</strong>se. then the cond ev<strong>al</strong>uates the corresponding consequents in that<br />

"clausc", r<strong>et</strong>urning as its v<strong>al</strong>ue the vatuc(s) of the last one. unless there were no<br />

consequents. in which case the v<strong>al</strong>ue of the cond is the v<strong>al</strong>ue of the predicl1le ev<strong>al</strong>uation.<br />

\ ..... It... \,....~. ,<br />

I"",",. 1 .. 1 ,.1\<br />

(p2 c2)<br />

(t e»<br />

is equiv<strong>al</strong>ent to<br />

( if pI cl<br />

(if p2 cl e»<br />

however cond <strong>al</strong>10ws multiple consequents. and <strong>al</strong>so may more clearly show the selection<br />

by clearly listing the sequenti<strong>al</strong>ly processed tests.<br />

If a11 of the predicates are f<strong>al</strong>se. then cond r<strong>et</strong>urns nil.<br />

when predic<strong>al</strong>e-/onn {consequent-form}­<br />

(when predicate-form<br />

consequent-J<br />

consequent-2<br />

cOllsequent-n)<br />

==><br />

(cond (predicate-form<br />

consequent-J<br />

consequent-]<br />

cOl1scquelll-n) )<br />

If predicQte-/onn ev<strong>al</strong>uates non-nuU. then the cOllsequl'llt-jOnns are eva1uated in order and<br />

the v<strong>al</strong>uc(s) of the last one r<strong>et</strong>urned as the v<strong>al</strong>ue of the when fonn: otherwise. the when<br />

fonn r<strong>et</strong>urns nit<br />

MC:NfLMAN:PCONS 81<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong><br />

29 Condition<strong>al</strong>s<br />

un les s predicate-fonn {collsequelll-jhml}·<br />

( un 1 e s s predicate-fonn<br />

consequent-I<br />

cOllsequent-2<br />

consequent-n)<br />

==><br />

(when (not predicate-Jon,,)<br />

c0l1sequclII-1<br />

COIlSl'quCllt-2<br />

c0l1sequel1t-11 )<br />

==><br />

(cond « not predicate)<br />

consequelll-I<br />

. cOllsequelll-2<br />

cotlsequent-n) )<br />

and {tOnn}·<br />

Ev<strong>al</strong>uates each fonn. and if any r<strong>et</strong>urns nil. and immediately r<strong>et</strong>urns nil without<br />

ev<strong>al</strong>uating any subsequent forms; otherwise, the result of the and is the v<strong>al</strong>ue(s) of the<br />

last foml. (and) = > t.<br />

or {fonn}·<br />

Ev<strong>al</strong>uates each fonl1, and if one r<strong>et</strong>urns a non-null result. that v<strong>al</strong>ue is r<strong>et</strong>urned by or .<br />

without ev<strong>al</strong>uating any of the following forms. (or) = > nil.<br />

or is supposed to r<strong>et</strong>urn exactly one v<strong>al</strong>ue, no matter how many were produced by the<br />

ev<strong>al</strong>uation of a form. except for the last fonl1 which is ev<strong>al</strong>uated tail-recursively (with<br />

respect to multiple v<strong>al</strong>ue propagation). It doesn't currently behave Quite this way.<br />

case keJfonn {(({key·}) {consequent}'}*<br />

A dispatch fonn utilizing the eql predicate. In gener<strong>al</strong>,<br />

(case keyform<br />

( (key-I-I key-I-2 .•. ) fonn-I-I form-I-2 .•• )<br />

( (key-2-1 key-2-2 .•. ) form-2-1 form-2-2 ••• )<br />

... )<br />

is essenti<strong>al</strong>ly the same as<br />

(l<strong>et</strong> «tern keyfonn»<br />

{cond « or (eql tern 'key-I-/) (eql tern 'kerl-2 ) .•. )<br />

/onn-i-I foml-I-] .•. )<br />

«or (eql tern 'key-]-/) (eql tern 'key-]-2) .•. )<br />

jOnn-2-1 /onn-2-2)<br />

... ) )<br />

Since the keys are constant. however. it is possible for the compiler to d<strong>et</strong>cnnine the<br />

cheapest way to perform the comparisons; see eql, page 20. In fact. if there are a<br />

moderate number of fixnum keys in a sm<strong>al</strong>l range. the <strong>NIL</strong> compiler may use the VAX<br />

CAS E instruction to perform the dispatching.<br />

MC:<strong>NIL</strong>MAN;PCONS 81<br />

23-DEC-83


Function I nvoc,ltion 30 <strong>NIL</strong> Manu<strong>al</strong><br />

In place of a list of keys. one may usc a single atomic key. Also. the symbols t and<br />

otherwise are speci<strong>al</strong>-cased and cause thaI "clause" to <strong>al</strong>ways be selected; no subsequent<br />

clauses will he examined. For example,<br />

(case (. 2 2) .<br />

(1 'one)<br />

(2 'two)<br />

(3 'three)<br />

(t 'many»<br />

=> many<br />

Nole that if one needs to lise nil. t. or otherwise as keys. they should he enclosed in a<br />

list: otherwise. nil wi11 be interpr<strong>et</strong>ed 4lS an empty list of keys. and t and otherwise as<br />

signifying the "ot.herwise" clause.<br />

This function is what selectq thought it would once be. and may be lIsed in place of<br />

MACI.IS., caseq.<br />

typecase ()l~;r(" {(/)1Jr-sprcijirr {limn},}--<br />

typeease examines each of its "clauses" in turn. If object is of the type specified by that<br />

I),pr-spcc{ficr (sec typep. page 18). then the ji,nlls in that clause arc e"<strong>al</strong>u4tted. and the<br />

v<strong>al</strong>ue of the last fonn is r<strong>et</strong>urned by typecase. If a 1)1JC-Spccijicr is one of the symbols t<br />

or otherwise. then that clause will <strong>al</strong>ways be selected. and <strong>al</strong>l subsequent clauses will be<br />

ignored.<br />

factoring out operations needed filf more th~lO oJleof the checks. The ;\IJ typecase docs<br />

not y<strong>et</strong> do any clever pointer';'lype dispatch, however.<br />

Remember that each "key" is a type specifier: it need not he just a type name. and it is<br />

definitely not a list of type names. To test for more than one type in one key, usc (or<br />

type! type) ... ).<br />

5.5 Function Invocation<br />

Often the function one desires to can is not constant: for instance. it may have been passed<br />

in as an argument (like the second argument to sort. page 55. or as a :test key worded argument<br />

to member. page 61. or som<strong>et</strong>hing obtained from a propeny list. hash table. or association .list).<br />

<strong>NIL</strong> does not suppon the old "function<strong>al</strong> variable" interpr<strong>et</strong>ation of a function<strong>al</strong> fonn; that is, in<br />

a fonn like (foo x y). the function c<strong>al</strong>led is never obtained from the v<strong>al</strong>ue of a variable foo.<br />

Instead. because the "name space" for functions and variables is compl<strong>et</strong>ely distinct, so speci<strong>al</strong><br />

functions are provided for invoking functions which are obtained by "norm<strong>al</strong>" ev<strong>al</strong>uation.<br />

tunea 11 fone/ion &rest orgs<br />

funeaU caUs junctioll on aU of the arguments in orgs. It is 1101 a speci<strong>al</strong> fonn; the<br />

junctiull is ev<strong>al</strong>uated in the regular filshion. and that v<strong>al</strong>ue should be a function. For<br />

instance. sort (page 55). which could be defined som<strong>et</strong>hing like<br />

(defun sort (sequence pred &k~y key) ... )<br />

could invoke its pred argument with som<strong>et</strong>hing like<br />

MC:NJI.MAN:PCONS 81<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 31 Iteration Constructs<br />

(func<strong>al</strong>l pred (elt sequence i) (elt sequence j»<br />

apply fullction &rcst args<br />

apply is somewhat like func<strong>al</strong>l. but the last of the args is a list of the remaining<br />

arguments to invoke /unctioll on. That is~ if apply is c<strong>al</strong>led like<br />

( app 1 y jil af a2 .•• <strong>al</strong>l list)<br />

then III will be invoked like<br />

(func<strong>al</strong>l In aJ a2 .•. <strong>al</strong>l el e2 ... em)<br />

where eJ c2 ... em are the clements of list.<br />

Often. the last argument tu apply is a list which is thc \'<strong>al</strong>uc of an &rest \ariab}e. 1 n<br />

~IL. this Jist may instead be a simple vector (it must be simple). as might be obtained by<br />

use of &restv instead of &rest.<br />

.Note that the ~1ACLISP apply function only acceptli two arguments. if you don't count the<br />

option<strong>al</strong> third argument which is an ev<strong>al</strong>uation environment.<br />

lexpr-func<strong>al</strong>1 jUllction & rest args<br />

Old name for what is now done hy apply. lexpr-func<strong>al</strong>l. unlike apply, is compatible<br />

with MACUSP.<br />

5.6 Iteration Constructs<br />

5.6.1 Mapping Functions<br />

mapc junction list &rest more-lists<br />

map 1 jullction list &rest more-lists<br />

mapcar jullction list &rcst more-lists<br />

map 11 s t junction lisl &rest more-lists<br />

mapcan function list &rest more-lists<br />

mapcon junction list &rest more-Iisls<br />

These arc the standard complement of USP mapping functions. which iterate down <strong>al</strong>l of<br />

the lists in par<strong>al</strong>lel. They accumulate results in three different ways, and apply jUnction in<br />

two different ways. In <strong>al</strong>l cases, if more than one list is supplied, they are stepped in<br />

par<strong>al</strong>lel and the iteration tenninates when the end of the shortest one is reach.<br />

mapc and mapl each r<strong>et</strong>urns its first argument as its· v<strong>al</strong>ue; that is, they are typic<strong>al</strong>ly for<br />

effect. mapc applies IUllctfgn to the cars of successive sublists, that is, to the elements of<br />

the lists. whereas mapl applies Iunction to the sublists themselves. Thus,<br />

(mapc #'print '(a be»<br />

prints<br />

a<br />

b<br />

e<br />

whereas<br />

(mapl #'print 9(a be»<br />

prints<br />

MC:<strong>NIL</strong>MAN:PCONS 81<br />

23-DEC-83


Ill'ration Constructs<br />

32 Nil. Manuul<br />

(a b c)<br />

(b c)<br />

(c)<br />

Both rcturn lisi. their first argument. Note that the function is not c<strong>al</strong>led on the nun list,<br />

evcn though thm might be thought of as a sublist. Random example where the r<strong>et</strong>urn<br />

v<strong>al</strong>ue is useful:<br />

(mapl "(lambda (subl)<br />

(rplacd subl (del<strong>et</strong>e (car subl) (cdr subl»»<br />

some-list)<br />

eliminatcs (dcstnlctively) <strong>al</strong>l duplicate element~ from some-list.<br />

mapl is what used tu be c<strong>al</strong>led map in MACI.lSI).·<br />

function (p4t£e 54).<br />

map is now a generic sequence<br />

mapcar and mapfist each r<strong>et</strong>urns a list of thercsull~ uf appJying JUl1eliol1 to tJlcir<br />

successive arguments: for map car. as with mapc. the arguments are the clements ofthc<br />

lists. and for maplist. as with mapf. they ar~ the sllblists themselves. For eXilmple:<br />

(mapcar #'(lambda (x y) (plus x y»<br />

• (1 2 3) • (9 10. 11»<br />

=> (10 1214)<br />

That could have been. written as<br />

(mapcar #'plus ... )<br />

mapcan :!nd mapccn "$p!ic~ tog~th~r" the results of applying ju;;Nivn to its succeSSive<br />

arguments. using (essenti<strong>al</strong>ly) nconc. One common usc of mapcan is to mapcar<br />

condition<strong>al</strong>ly:<br />

(mapcan #'(lambda (x) (and (pred x) (list (fx»»<br />

smne--Iist)<br />

is kind of like doing (mapcar # '/ some-list) having first del<strong>et</strong>ed those elements which do<br />

not satisfy pred.<br />

Because of the constrained nature of the iteration, mapcar, maplist. mapcan, and<br />

mapcon probably generate b<strong>et</strong>ter code than you (oreveD som<strong>et</strong>hing like the loop macro)<br />

could write for generating the r<strong>et</strong>urn v<strong>al</strong>ue.<br />

5.6.2 Other Iteration Forms<br />

dot 1mes (var count [end/onn]) {dec/aration}- {tag I fonn}-<br />

var is stepped from 0 (inclusive) to the v<strong>al</strong>ue of count (exclusive); for each v<strong>al</strong>ue, each of<br />

the /onns is ev<strong>al</strong>uated. When the iteration tenninates. the v<strong>al</strong>ue of end/onn is r<strong>et</strong>urned.<br />

The "body" of dotimes is a "tagbody" body (sec tagbody). Atomic tags may be inscncd<br />

among the forms and jumped to with go (page 34), to produce strange and wondrous<br />

unstructured code.<br />

AdditionaHy. dotimes establishes an implicit block named nil around the dotimes fonn<br />

(sec block): one may thus use r<strong>et</strong>urn (or r<strong>et</strong>urn-from with a block nrune of nil) to exit<br />

and r<strong>et</strong>urn a vaJuc(s) from the dotimes. without running exit/ann. block and tagbody<br />

are described in section 5.6.3, page 34.<br />

MC:<strong>NIL</strong>MAN:PCONS 81


<strong>NIL</strong> Manu<strong>al</strong> 33 Iteration Constructs<br />

dolist (var list [cndfimn]) {declaration}* {tag I jiJnn}*<br />

Similar to dotimes. hut steps var through the clements of list. the way mapc (page 31)<br />

d\)es.<br />

dovector (var vCClor) {declar<strong>al</strong>ion)· {tag I fonn)·<br />

Similar to dolist. but for vectors. dovector will work on any type of vector: its' name<br />

and existence dates from the early days of <strong>NIL</strong> when <strong>al</strong>l vectors were simple vectors. If<br />

vcctor is going to be of some known speci<strong>al</strong>ized type. one might be able to g<strong>et</strong> b<strong>et</strong>ter<br />

code hy llscing one of the speci<strong>al</strong>ized loop constnu:L4iavailable in NIl.. as discussed in<br />

section 17.7.1.2. page 163.<br />

do ({var [inil [s/cp]])' {cndlcst {el1lljiJnl1}*) {declar<strong>al</strong>iol1}· {lag I form}·<br />

do is a more gener<strong>al</strong> iteration constnlCt. The specified variables arc bound in par<strong>al</strong>lel (as<br />

by l<strong>et</strong>. page 26) to the v<strong>al</strong>ues of the corresponding initi<strong>al</strong> v<strong>al</strong>ues. These are their v<strong>al</strong>ues<br />

,for the first iteration. For <strong>al</strong>l subsequent iterations. the variables which have step forms<br />

specified are <strong>al</strong>l s<strong>et</strong> in par<strong>al</strong>lel to the v<strong>al</strong>ues of those step forms. (That is. the v<strong>al</strong>ues of<br />

<strong>al</strong>l of the step forms are computed b~fore <strong>al</strong>lY of the assignments have been made.)<br />

On each iteration. elldlest is ev<strong>al</strong>uated. If the result is not nil. then the iteration<br />

terminates and e\'<strong>al</strong>u~tes the elld/onus as an implicit progn (r<strong>et</strong>urning nil if there arc no<br />

elldfonns). Otherwise, the "body" of the do is interpr<strong>et</strong>ed as by tagbody (page 34).<br />

Thus.<br />

( do ( ... ) (n i 1) tagbody ... )<br />

( do (...) (t ... ) tag body . . . )<br />

will never g<strong>et</strong> around to interpr<strong>et</strong>ing the forms in tagbody.<br />

do establishes an implicit block named nil around the entire do fonn: see section 5.6.3.<br />

page 34.<br />

As a speci<strong>al</strong> hack for MACLISP code. if endrest is not specified (and hence no endfonus<br />

could be specified). then the body of the do is interpr<strong>et</strong>ed exactly once. and nil r<strong>et</strong>urned;<br />

that is. the do should have been written as prog (page 35), except that MACLISP prog<br />

docs not accept initi<strong>al</strong> v<strong>al</strong>ues for the variables.<br />

do.<br />

The MACLISP "old style do" is <strong>al</strong>so supponcd in <strong>NIL</strong>. This takes the fonn<br />

( do var inil step elldtest tagbody ••• )<br />

and is equiv<strong>al</strong>ent to<br />

(do « var init step» (endtest)<br />

tagbody • .. )<br />

New code should not use this fonnat.<br />

Speci<strong>al</strong>fonn<br />

({(var [illil [step]])} -> {endtest {endfoml) -> {declaration)· {tag I fonn}·<br />

Ihis is like do, except that the variables are bound to their initi<strong>al</strong> v<strong>al</strong>ues sequenti<strong>al</strong>ly (like<br />

l<strong>et</strong>- (page 26) rather than J<strong>et</strong>). and the steps are <strong>al</strong>so performed sequenti<strong>al</strong>ly (like s<strong>et</strong>q<br />

rather than ps<strong>et</strong>q).<br />

MC:<strong>NIL</strong>MAN;PCONS 81<br />

23-DEC-83


Iteration Constructs 34 <strong>NIL</strong> Manu<strong>al</strong><br />

See "Iso the loop macro, page 144. loop is a "programmahle iteration facility". which <strong>al</strong>lows<br />

one to combine various sorts of iterations (such as those provided by dotimes and dovector) with<br />

vilrious sorts of result accumuhttion (such as those provided by mapcar. mapcan. every. some.<br />

and other things such as summing and counting). Because it is complicated. it is documented<br />

fully in Ch4tptcr 17. page 144. An earlier version of that chapter appeared as [51. which is<br />

expected to be re.vised· similarly.<br />

5.6.3 Block and Tagbody<br />

block Clnd tagbody tog<strong>et</strong>her implement the flow-of-control function<strong>al</strong>ity pf()\'idcd hy standard<br />

prog. prog could have been implcmcnted as a milCro in terms uf these and l<strong>et</strong>. and in fil<strong>et</strong> is<br />

descrihed in that filshion by COMMON LISP.<br />

block nome {declar<strong>al</strong>ion}- ljorm}*<br />

block· ev<strong>al</strong>uates the jiJrms. If a lcxicaJly apparent r<strong>et</strong>urn-from is ev<strong>al</strong>uated with a tag of<br />

lIome (or l1ame is nil arid a r<strong>et</strong>urn is ev<strong>al</strong>uated). then the vaJue(s) of the form given to<br />

r<strong>et</strong>urn or r<strong>et</strong>urn-from arc r<strong>et</strong>urned as the \"<strong>al</strong>ue of the block form. Otherwise'. the block<br />

filrm r<strong>et</strong>urns the v<strong>al</strong>uc(s)uf the ev<strong>al</strong>umion of the lClst fonll.<br />

Note that the argument to r<strong>et</strong>urn or r<strong>et</strong>urn-from is ev<strong>al</strong>uated in the environment in<br />

which it occurs, 1101 the environment where the block was established.<br />

r<strong>et</strong>urn fonn<br />

Ev<strong>al</strong>uates jbnl1 , and r<strong>et</strong>urns the v<strong>al</strong>ue(s) it r<strong>et</strong>urns from the nearest lexic.llly apparent<br />

block with a name of nil. Many speci<strong>al</strong> forms implicitly establish blocks named nil. such<br />

as prog. do. do list. dotimes, dovector, and (usu<strong>al</strong>ly) loop.<br />

Note that this differs subtly from LISP MACIIINFl.JSP. In LlSI' MA(,IU~F. I.JSP. r<strong>et</strong>urn<br />

r<strong>et</strong>urns from the innermost prog (Le.. block) which is 1101 named t. In <strong>NIL</strong> (and COMMON<br />

LISP), a r<strong>et</strong>urn to a block name of nil only matches a block name of nil, and the block<br />

name t is not distinguished in any way.<br />

r<strong>et</strong>urn-from name form<br />

Ev<strong>al</strong>uates fonn, and r<strong>et</strong>urns the v<strong>al</strong>ue(s) it r<strong>et</strong>urns from the nearest lexic<strong>al</strong>ly apparent<br />

block with a name of name. name is not ev<strong>al</strong>uated.<br />

tagbody {tag J form}-<br />

The body of a tagbody is examined sequenti<strong>al</strong>ly. If a fonn is atomic. then it is a tag and<br />

is ignored, otherwise it is ev<strong>al</strong>uated. If during the ev<strong>al</strong>uation a lexica11y apparent c<strong>al</strong>l to<br />

go is ev<strong>al</strong>uated with an argument of one of the tags. then control is r<strong>et</strong>urned to that<br />

point within the tagbody fonn. which resumes its interpr<strong>et</strong>ation. If the interpr<strong>et</strong>ation<br />

reaches the end of the tagbody. the result is nit<br />

MC:NII.MAN:PCONS81<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 35 Non-Loc<strong>al</strong>l-"hl\\ of Control<br />

It is important to note that the name matching of block/r<strong>et</strong>urn-from and tagbody/go is<br />

lexic<strong>al</strong>. For instance.<br />

(defun f (x)<br />

(block foobar<br />

(g #'(lambda (x) (r<strong>et</strong>urn-from foobar x» x»)<br />

(defun 9 (fn x)<br />

(list (block foobar<br />

(func<strong>al</strong>l fn x»»<br />

(f 'faa) => faa<br />

not (faa). The 7\11_ compiler cannot handle this example. however. Also. the named hlock only<br />

has l~rll<strong>al</strong>l1i(' e.rlclIl: if an attempt is made to r<strong>et</strong>urn (0 a lexic<strong>al</strong>ly apparent block construct which<br />

has been exited. the interpr<strong>et</strong>er will complain.<br />

prog I'or/ist {dcdar<strong>al</strong>ion)* {lag I form}*<br />

_Swndard prog. l'arlisl may be a list of variables. or a list of lists of variables and their<br />

initi<strong>al</strong> v<strong>al</strong>ues. They will be bound in par<strong>al</strong>lel. prog can be built from the above<br />

primitives:<br />

( 1 e t varUs!<br />

Ihe dec/a rations<br />

(block nil<br />

(tagbody the lags <strong>al</strong>ldfonlls) ) )<br />

For compatibility with LISP MACHINE LISP. if the first "argument" to prog is a non-null<br />

"tuill. then th~t is uscd as thc jjam~ lif the blo~k.. wiih tlic \l<strong>al</strong> ii!)l ruiiuwiJJ~.<br />

prog. \Iar/ist {declaratioll}* {lag I Jon,,}*<br />

Like prog. but binds the variables sequenti<strong>al</strong>ly rather than in par<strong>al</strong>lel. i.e.. like using l<strong>et</strong>.<br />

(page 26) rather than l<strong>et</strong>.<br />

5.7 N on-Loc<strong>al</strong> Flow of Control<br />

catch tag {{ann}*<br />

COMMON USP catch. lag is ev<strong>al</strong>uated and the result saved. Then. if during the<br />

ev<strong>al</strong>uation of the fonus. if a throw to that tag (as tested for by eq) occurs, the catch<br />

fonn so named will r<strong>et</strong>urn the v<strong>al</strong>ues given to the throw. The tag so named has dynamic<br />

extent.<br />

The tag to catch is <strong>al</strong>lowed to be any LISP object. This means that one can generate a<br />

guaranteed unique tag by (for instance) (ncons nil). or by using a datastructure which is<br />

somehow associated with the control point of the catch. This is. in fact. how the <strong>NIL</strong><br />

interpr<strong>et</strong>er implements the block and tag body constructs; it uses the datastructures in<br />

which it stores its control-flow infonn~ltion as tags to catch.<br />

Note that this is incompatible with the standard MACI.ISP catch function documented in<br />

the 1974 manu<strong>al</strong> ([9]). However. PDPIO MACUSP has been bitching and moaning about<br />

use of catch for some year or more now. advising the use of .catch instead (which is<br />

equiv<strong>al</strong>ent to <strong>NIL</strong>'s catch).<br />

MC:<strong>NIL</strong>MAN:PCONS 81<br />

23-DEC-83


Multiple V<strong>al</strong>ues 36 Nil. Manu<strong>al</strong><br />

throw lag ibnn<br />

Itlg and ji>nl1 are ev<strong>al</strong>uated. Control is r<strong>et</strong>urned from the nearest catch established with a<br />

tag eq to the v<strong>al</strong>ue of tag. and that catch then r<strong>et</strong>urns <strong>al</strong>l the v<strong>al</strong>ues produced by fonn.<br />

speci<strong>al</strong> form because of mUltiple v<strong>al</strong>ue passb.lck. of course that doesn't work reliably y<strong>et</strong>.. ..<br />

Note that this is incompatible with the old-fashioned MACI.lSP throw function. However,<br />

in PDPlO MACI.JSP throw has been out of vogue for some time, supplanted by * throw.<br />

which has syntax and semantics identic<strong>al</strong> to this throw. and which is supported in 1'11 .•<br />

unw1nd-protectpmtcC(('ti-.l'onll {dCdllup-jonn)*<br />

prolcclcd-jimll is ey<strong>al</strong>mlted. and the result r<strong>et</strong>urned. Upon exi( the ('/eclllup-/CJnIlS arc<br />

ev<strong>al</strong>uated. No matter how the exit is achieved (throw. error. whatever).<br />

In principle. unwind-prote~t r<strong>et</strong>urns wh~ltever extra v<strong>al</strong>ues protected-jon" did. In the<br />

current 'implementation. this cannot be guaranteed bccnusc no state is saved around the<br />

ev<strong>al</strong>uation of the c/l'lIIlUp-/onlls.<br />

*catch tag {lbnll}*<br />

Old name fi1r what is now catch. Wi1l be supported ~md identic<strong>al</strong> to what catch is now<br />

indefinitely. for the sake of MACLISP programs. which use this name with identic<strong>al</strong> syntax.<br />

(Note however that MACLISP catch <strong>al</strong>lows lag to be a list of tags. which means it can't be<br />

just any object.)<br />

*throw tag jonn<br />

Old name for what is now throw. Will be supponed and identic<strong>al</strong> to wheat throw is now<br />

indefinitely. for the sake of MAOJSP programs. which use this name with identic<strong>al</strong> syntax.<br />

This seems to be an ordin


-<br />

<strong>NIL</strong> Manu<strong>al</strong> 37 Multiple V<strong>al</strong>ues<br />

v<strong>al</strong> ues -11 s t list<br />

R<strong>et</strong>urns as multiple v<strong>al</strong>ues <strong>al</strong>l the clements of list.<br />

v<strong>al</strong> ues -vector veclOr<br />

Because ~Il. makes such great usc of vectors. this is provided <strong>al</strong>so; it r<strong>et</strong>urns a11 the<br />

elements of vector as multiple v<strong>al</strong>ues.<br />

For example. in Nil. v<strong>al</strong>ues is defined by<br />

{defun v<strong>al</strong>ues (&restv vee)<br />

(v<strong>al</strong>ues-vector vee»<br />

Of course. the ~ll compiler will open-compile a caB to v<strong>al</strong>ues.<br />

mul t 1p 1 e-v<strong>al</strong> ue variables v<strong>al</strong>ues-foml<br />

The variables in variables. which must be a list of variables. are s<strong>et</strong> to the corresponding<br />

!11U1liplc v<strong>al</strong>ues r<strong>et</strong>urned by the ev<strong>al</strong>uation of v<strong>al</strong>ues-funn. Extra v<strong>al</strong>ues are ignored: if too<br />

few v<strong>al</strong>ues are r<strong>et</strong>urned. the extra variables are s<strong>et</strong> to nil.<br />

multiple-v<strong>al</strong>ue <strong>al</strong>ways r<strong>et</strong>urns exactly' one v<strong>al</strong>ue. the v<strong>al</strong>ue of the first v<strong>al</strong>ue r<strong>et</strong>urned by<br />

,'<strong>al</strong>ues-fun1l (or nil if none were r<strong>et</strong>urned).<br />

In <strong>NIL</strong>. as in USP MACHINE USP. one may use nil in place of a variable to cause the<br />

corresponding v<strong>al</strong>ue to be ignored. This is specific<strong>al</strong>ly dis<strong>al</strong>lowed by COMMON l.ISP. and<br />

should not be used. The preferred way to handle this uses multiple-v<strong>al</strong>ue-bind, below.<br />

The name of this will be changed to multipte-v<strong>al</strong>ue-s<strong>et</strong>q by COMMON LlSP ...<br />

mul t 1 ple-v<strong>al</strong> ue-b1 nd variables v<strong>al</strong>ues-fonn {declaration}* {{onn}*<br />

Somewhat like multiple-v<strong>al</strong>ue. except the variables in variables are bound to the v<strong>al</strong>ues<br />

produced by v<strong>al</strong>ues-form. and each of the fonns ev<strong>al</strong>uated in that environment.<br />

Note that. <strong>al</strong>though in <strong>NIL</strong> nil may be used as a placeholder in variables for a v<strong>al</strong>ue<br />

which will not be used, it may not in COMMON LISP. The preferred way to ignore a<br />

v<strong>al</strong>ue is to use a name for it, and deClare that name to be ignored; for instance.<br />

(multiple-v<strong>al</strong>ue-bind (quo rem) (%bignum-quotient-norm x y)<br />

{declare (ignore quo»<br />

(hack-about-with rem»<br />

This addition<strong>al</strong>ly provides the benefit of having the v<strong>al</strong>ue "documented" by vinue of<br />

being associated with a named variable.<br />

mult1ple-v<strong>al</strong>ue-l1st jOnn<br />

fonn is ev<strong>al</strong>uated. and <strong>al</strong>l of the v<strong>al</strong>ues it produces are r<strong>et</strong>urned as a list. For example:<br />

(multiple-v<strong>al</strong>ue-list (v<strong>al</strong>ues 1 2» => (1 2)<br />

(multiple-v<strong>al</strong>ue-list (v<strong>al</strong>ues» => nil<br />

mult1ple-v<strong>al</strong>ue-progl first-fon" {fOnn}*<br />

.This is likc progl (page 22). but r<strong>et</strong>urns <strong>al</strong>l of the v<strong>al</strong>ues produced by the ev<strong>al</strong>uation of<br />

firsl-jonn. progl is supposed to r<strong>et</strong>urn only the first v<strong>al</strong>ue, never the other v<strong>al</strong>ues;<br />

however. in the current multiple v<strong>al</strong>ue implementation <strong>NIL</strong> uses, this cannot be depcnded<br />

on.<br />

MC:<strong>NIL</strong>MAN;PCONS 81<br />

23-DEC-83


Gener<strong>al</strong>ized Variables 38 <strong>NIL</strong> Manu<strong>al</strong><br />

5.9 (.ener<strong>al</strong>izcd Variables<br />

S 8 t f {pI lice v<strong>al</strong>ue} ...<br />

s<strong>et</strong>f is sort of a gener<strong>al</strong>ized s<strong>et</strong>Q. Essenti(ll1y. a s<strong>et</strong>f fonn expands into the code needed<br />

to store each v<strong>al</strong>ue into each plac(,. For example. just as<br />

(s<strong>et</strong>q x 3)<br />

stores 3 intox.<br />

(s<strong>et</strong>' (car 1) 5)<br />

stures 5 inw the car of the vaJue of J. As with s<strong>et</strong>q. multiple p141ce/v<strong>al</strong>ue pairs ,Ire<br />

handled sequenti<strong>al</strong>ly.<br />

s<strong>et</strong>f <strong>al</strong>ways r<strong>et</strong>urns the hlst v,due stored.<br />

s<strong>et</strong>f works on variahles. aU dcfincd car/cdr functions. array and scquence accessing<br />

functions (aref. elt. vref. char. bit). g<strong>et</strong>. various attribute accessors (symbol-plist..<br />

symbol-v<strong>al</strong>ue. symbol-function. <strong>et</strong>c.). and <strong>al</strong>l accessors defined by either defstruct or<br />

defffavor. In fact. it is the canonic<strong>al</strong> (and the only fonn<strong>al</strong>ly defined) way to modify slots<br />

of structures defined with defstruct. It <strong>al</strong>so operates on a number of low-level <strong>NIL</strong><br />

primitives. including nibble. g<strong>et</strong>-a-byte. and g<strong>et</strong>-a-byte-2c.<br />

s<strong>et</strong>f <strong>al</strong>so operatcs on certain other fonns whose "inversions" are not strictly side-effecting,<br />

by pcrfonning the s<strong>et</strong>f on an argument of the function (which must be v<strong>al</strong>id as a place to<br />

s<strong>et</strong>f). Thesc include Idb and load;..byte. For instance, the side-cffect perfonncd by<br />

{~ptf (lt1h hyflJspec place) ."<strong>al</strong>}<br />

is the samc as<br />

(s<strong>et</strong> f place ( dpb \I<strong>al</strong> bYlespcc place»<br />

<strong>al</strong>though· the r<strong>et</strong>urn v<strong>al</strong>ue should be different.<br />

The s<strong>et</strong>' mcthodology is even more helpful when the logic<strong>al</strong> operation being perfonncd on<br />

the place is "read-modify-writc". This means that the place needs to only be specified once in the<br />

form.<br />

As of this writin& the COM~ON LISP compatible s<strong>et</strong>f has not y<strong>et</strong> been insta11ed in <strong>NIL</strong>, so<br />

not <strong>al</strong>l of the following macros may be in the <strong>NIL</strong> when it is released. This pertains to incf,<br />

decf, shiftt, and rotatef. and anything having to do with how one might define such a macro.<br />

s<strong>et</strong>f. push. and pop have been in <strong>NIL</strong> for some time <strong>al</strong>ready.<br />

pus h item place<br />

Approximately<br />

(s<strong>et</strong> f place (cons item place»<br />

except that order of ev<strong>al</strong>uation is preserved, and the forms of place are ev<strong>al</strong>uated only<br />

once.<br />

pop place<br />

Approximately<br />

(p rag 1 (car place) (s<strong>et</strong>f place (cdr place»<br />

but the fonns in place are ev<strong>al</strong>uated only oncc. In otherwords, pop treats the contents of<br />

place as a list stack~ it r<strong>et</strong>urns the top of the stack and pops it<br />

MC:<strong>NIL</strong>MAN;PCONS 81<br />

23~DEC-83


NIl. Manu<strong>al</strong><br />

39<br />

Property I -ists<br />

1 nct placc &option<strong>al</strong> (drlta I)<br />

S<strong>et</strong>s placc to plaer plus della.<br />

dect place &option<strong>al</strong> (della I)<br />

S<strong>et</strong>s plac(' to place minus delta.<br />

shittf place! place) ... placell fonn<br />

( s h i f t f place jbnl1)<br />

is just like using s<strong>et</strong>f.<br />

(shi ftf place!· place) /i,nl1)<br />

stores the v<strong>al</strong>uc of placel into pluce!. and then the v<strong>al</strong>ue of form into place2.<br />

rotat<strong>et</strong> placel placc) ... placcll<br />

rotatef "roUltes" the v<strong>al</strong>ue of the places. '111e v,llue of place} is stored into placc/.<br />

place] into place) <strong>et</strong>c., and placcl into placen. <strong>al</strong>l in par<strong>al</strong>lel.<br />

5.10 Property Lists<br />

A properly list is a list of even length. of <strong>al</strong>ternating indicators and v<strong>al</strong>ues. 'Illis is. of course.<br />

the same datastructure which is the property list of a symbol. Note that this is not the same as a<br />

disembodicd property list. which has odd length. COMMO!' LISP has gener<strong>al</strong>ized the property list<br />

mechanism so that is attached neither specific<strong>al</strong>ly to symbols or disembodied property lists, but<br />

rather interfaces to gener<strong>al</strong>ized variables.<br />

Note: as of this writing. the CO\1MON l.ISP compatible s<strong>et</strong>f. on which both remf and s<strong>et</strong>f on<br />

g<strong>et</strong>f are dependent. has not been inst<strong>al</strong>led in <strong>NIL</strong>. As a result. there is a chance they might not<br />

appear in this release.<br />

g<strong>et</strong>t place indicator &optionat default<br />

g<strong>et</strong>f f<strong>et</strong>ches the v<strong>al</strong>ue under the indicator indicator from the property list which place<br />

ev<strong>al</strong>uates to. If no such indicator exists, then default is r<strong>et</strong>urned. The standard MACLISP<br />

g<strong>et</strong> function could have been written as<br />

(defun g<strong>et</strong> (x indicator)<br />

(typecase x<br />

(symbol (g<strong>et</strong>f (symbol-plist x) indicator»<br />

(cons (g<strong>et</strong>f (cdr x) indicator»<br />

(t error»)<br />

It is not re<strong>al</strong>ly necessary for place to actu<strong>al</strong>ly be a gener<strong>al</strong>ized variable. However, g<strong>et</strong>f<br />

may be used with s<strong>et</strong>f (and <strong>al</strong>l such similar constructs). in which case place obviously<br />

must be such a thing. MACLISP putprop could have been written as<br />

(defun putprop (x v<strong>al</strong>ue indicator)<br />

(typecase x<br />

(symbol (s<strong>et</strong>f (g<strong>et</strong>f (symbol-plist x) indicator) v<strong>al</strong>ue»<br />

(cons (s<strong>et</strong>f (g<strong>et</strong>f (cdr x) indicator) v<strong>al</strong>ue»<br />

(t error»)<br />

MC:<strong>NIL</strong>MAN:PCONS 81<br />

23-DEC-83<br />

- --<br />

" '",', i" , "" ,:;.~:>;~.({~/;,: • ' , " '


.Jo _ • .... ' _ ~<br />

Propeny loists 40 <strong>NIL</strong> Manu<strong>al</strong><br />

'111(' utility of g<strong>et</strong>f is that it may be used to manipulate "property 1isl~" stored in p14lCCS<br />

other lhan symbols or the cdr of a cons. One might. fi)r instance. define a structure<br />

with defstruct (page 125) which has one SIOl used to hoJda property list:<br />

(defstruct (frobozz :named :conc-name)<br />

initi<strong>al</strong>-data<br />

plist<br />

(hyperspace~shift-co~nt O})<br />

Then. items in the "property list" may be accessed by<br />

( ge t f (f robozz-p 1 is t /robozz) illdi('i1Ior)<br />

and s<strong>et</strong> by<br />

(s<strong>et</strong> f (g<strong>et</strong> f (frobozz-p 1 is t /mb()zz) iJllJictltor) Ilafue)<br />

One may <strong>al</strong>so do such things as<br />

(incf (g<strong>et</strong>f (frobozz-plist jrobozz) indicator»<br />

to increment a v<strong>al</strong>ue stored on tlle propcnyJisL<br />

remf plac£' indicator<br />

remf removes an indicator/v<strong>al</strong>ue pair from the property list in place. In order to do so.<br />

place must be a gener<strong>al</strong>ized variable usable with self remf r<strong>et</strong>urns nil if there was no<br />

such pair for indicator, t otherwise.<br />

g<strong>et</strong>-propert 1es place names<br />

g<strong>et</strong>-properties <strong>al</strong>lows one to search for a s<strong>et</strong> of properties, It looks down the property<br />

list in place: when an indicator is found which· is in the list names, then it r<strong>et</strong>urns three<br />

Vu!uC3: u'Jc ·.."luc under that IndkaLui. iIi\:: indk'ilUi. and th~ suhIi~i uf i.h~ 1.IIUV\:1 i.y ii~i.<br />

beginning with the indic<strong>al</strong>Of. (Thu~ the car of that sublist is the indicator. and the cadr<br />

the v<strong>al</strong>ue. This last v<strong>al</strong>ue is what is r<strong>et</strong>urned by the MACLlSP g<strong>et</strong> I function. page 69.) ]f<br />

none of the indicators specified in names are found, then <strong>al</strong>1 three v<strong>al</strong>ues g~t-properties<br />

r<strong>et</strong>urns arc nil.<br />

Not only can g<strong>et</strong> - properties be used for searching for more than one indicator at once,<br />

but the third v<strong>al</strong>ue r<strong>et</strong>urned can be fed back to g<strong>et</strong>-properties to continue searching<br />

from that (or some later) point in the propeny list<br />

Note <strong>al</strong>so the property-list function g<strong>et</strong> (page 65) and remprop (page 65).<br />

MC:<strong>NIL</strong>~1AN:PCONS 81<br />

23-DEC-83<br />

" ,<br />

',-~", :" _ " r, ::.. -.' ' -', ::, _" "~,," ,-, "'" .-'::' .", :: ,';..:",,: ':;, ,,,,., ,', ,",;:: " • -~' "'~'"<br />

, .


<strong>NIL</strong> Manu<strong>al</strong> 41 I )eclarations<br />

6. Declarations<br />

In LISP. there is only one declaration that affects program semantics (and is thus the only one<br />

needed to make tJlem run correctly): the speci<strong>al</strong> declaration. All other declarations are for the<br />

purpose of providing extra information abollt the program-this infonnation may be for the<br />

compiler. for a code an<strong>al</strong>yzer, or just as documentation for humans. The assertions made by<br />

declarations may be tested by the l.ISJ> interpr<strong>et</strong>er or compiler in order to find program errors,<br />

and may be used to direct compilation strategies, so incorrect declarulions are illeg<strong>al</strong> and may<br />

cause erroneous results.<br />

6.1 Loc<strong>al</strong> Declarations<br />

The norm<strong>al</strong> declaration mechanism associates the declaration information with a particular<br />

context established by some speci<strong>al</strong> form or construct. This is what happens with a lambdaexpression.<br />

for instance. which is "described" as<br />

«(lambda lambda-list {declaration}. {jbn,,}.)<br />

{lonn}. )<br />

A dec/aration is either a fonn<br />

(dec 1 are {dec/-spec..})<br />

or a form which is a macro c<strong>al</strong>l which expands into such a declare form. Declarations are<br />

handled speci<strong>al</strong>ly by the forms they are within; it is an error for them to occur in other contexts.<br />

even though this may not be d<strong>et</strong>ected. The various speci<strong>al</strong> forms which accept declarations show<br />

"'w'here thGSC dcduiutiGns muy 4ippcar in their descriptions in this mam.i.iL Typk<strong>al</strong>ly, this is just<br />

preceding any "body" forms. as in the above examples. A dec/-spec is a list. the car of which<br />

must be a symbol which is recognized as naming some declaration; the possible symbols, and<br />

what they mean. are shown a bit below.<br />

Individu<strong>al</strong> declarations f<strong>al</strong>l into two categories: those which affect variable bindings, and those<br />

which do not. Those which do~ associate with bindings perfonned by the speci<strong>al</strong> construct they<br />

are associated with. For instance, both<br />

(lambda (a b c) (declare (type long-float e» .•. )<br />

(l<strong>et</strong> «a (f})(b (g» (c (h»)<br />

(declare (type long-float c»<br />

... )<br />

say that the variable c is being bound to som<strong>et</strong>hing of type long -float, and that that particular<br />

"instantiation" of c will <strong>al</strong>ways have a long-float as its v<strong>al</strong>ue. The declaration in effect "attaches"<br />

to the binding of the variable; only that particular binding is affected. The declaration in<br />

(l<strong>et</strong> «x (f»)<br />

(declare (type x Single-float»<br />

(l<strong>et</strong> «x (cons x y») ••• }<br />

... }<br />

only affects the outer binding of x, and makes no statement about the inner binding.<br />

declaration in<br />

The<br />

MC:<strong>NIL</strong>MAN;DCLS 31<br />

23-DEC-83<br />

~~ - . . . .....


Lo(<strong>al</strong> I )cciClfations 42 <strong>NIL</strong> Manu<strong>al</strong><br />

(l<strong>et</strong> «x (f»)<br />

(declare (type simple-vector v»<br />

· .. )<br />

is in error. because there is no variable v bcing bound in the construct the declare is associated<br />

with. l<strong>et</strong>.<br />

The other c~Jteg()ry of declaration is thepervasi\'t' declar<strong>al</strong>iOfl. which does not· associate with<br />

variable bindings. These have lexic<strong>al</strong> scope. delimited by the form the declaration occurs in. This<br />

sort of de clara lion is in effcct for (111 parts of the spcciul lbnn: this indudcssuch things as thnns<br />

which arc ev<strong>al</strong>uated to obtain v<strong>al</strong>ues for variables being hound. even if those forms arc not<br />

strictly part of the ttbody" of the spcci<strong>al</strong> «lnn. For inSi«Ulce. the optimize dccliJration in<br />

(l<strong>et</strong> «x (r») -<br />

(declare (type x single-float) (optimize (speed 3»)<br />

(l<strong>et</strong> «x (eons x y»))<br />

(mapc "(lambda (z) ... ) x)<br />

· .. )<br />

· .. )<br />

~s ttin effect" everywhere within the outer l<strong>et</strong>. unless it were to be loc<strong>al</strong>ly shadowed by another<br />

·.>ptimize declaration hidden in one of the fonns represented by the elipses. The fonn (f) to<br />

which the x in the outer l<strong>et</strong> is being bound. is affected by that declaration. On the other han


<strong>NIL</strong> Manu<strong>al</strong> 43 I.oc<strong>al</strong> I )ec larations<br />

6.1.1 The Speci<strong>al</strong> Declaration<br />

(speci<strong>al</strong> va,../ va,..] '"<br />

va,../l)<br />

The speci<strong>al</strong> declaration differs from <strong>al</strong>l other declarations in two ways:<br />

• It is the only declaration which affects program semantics. and<br />

• it is the only declaration which can both "attach to" variable bindings. and <strong>al</strong>so be a<br />

pervasive declaration.<br />

This du<strong>al</strong>ity is partly for convenience. but <strong>al</strong>so follows from what this declaration docs.<br />

For those variables in the speci<strong>al</strong> declaration which are being bound hy the speci<strong>al</strong> form the<br />

declaration is associated with. for instance x in<br />

(l<strong>et</strong> «x (f»)<br />

(declare (speci<strong>al</strong>.x y»<br />

fonus. .. )<br />

the declaration is an immedi<strong>al</strong>e. or variable-binding declaration. It says that the speci<strong>al</strong> v<strong>al</strong>ue of<br />

x should be bound. so that x has dynamic rather than lexic<strong>al</strong> scope. As a consequence of this.<br />

unshadowed references to x within the forms. will refer to the speci<strong>al</strong> v<strong>al</strong>ue of x-the one it was<br />

bound to. which is no doubt what is desired. This docs not affect bindings which arc not so<br />

declared: in<br />

(l<strong>et</strong> «x «f»)<br />

(declare (speci<strong>al</strong> x y»<br />

( 1 e t « x (g») ; x number 3<br />

. .. x ... ) ; x number 4<br />

... )<br />

the inner binding of x is a lexic<strong>al</strong>. rather than speci<strong>al</strong>. binding. because there is no speci<strong>al</strong><br />

declaration for it. This binding shadows the outer (speci<strong>al</strong>) binding of x. with the result that<br />

reference to x within that inner l<strong>et</strong> refers to the lexic<strong>al</strong> v<strong>al</strong>ue. which gives what (9) ev<strong>al</strong>uated to.<br />

This. then. is <strong>al</strong>l re<strong>al</strong>ly the same as how the type declaratitlO associated. as was described above.<br />

If. however. there are variables being declared speci<strong>al</strong> for which there no bindings. then the<br />

speci<strong>al</strong> declaration for them is a pervasive declaration, which affects their reference (it will stin not<br />

affect inner bindings). For instance. in both<br />

and<br />

(l<strong>et</strong> «x (f»)<br />

(declare (speci<strong>al</strong> x y»<br />

• .. y ..• )<br />

(l<strong>et</strong> «x (f»)<br />

(declare (speci<strong>al</strong> x y»<br />

(l<strong>et</strong> «x (9»)<br />

• •• x •••<br />

. ~. y ••. »<br />

the reference to y amidst the elipses is a speci<strong>al</strong> reference. due to the speCi<strong>al</strong> declaration for y.<br />

Note that by contrast the reference to x b<strong>et</strong>ween elipses is lexic<strong>al</strong> because of the shadowing effect<br />

of that inner lexic<strong>al</strong> binding.<br />

The example function find-<strong>al</strong>l-leaves from chapter 3. on page 12 (q.v.), can be rewritten as<br />

~IC:<strong>NIL</strong>M"N;DCLS 31<br />

23-DEC-83


Loc<strong>al</strong> Declarations 44<br />

<strong>NIL</strong> Manua1<br />

(defun find-<strong>al</strong>l-1eaves (tree)<br />

( 1 e t «. 1 e a v e s • nil» ; Empty s<strong>et</strong> ofleaves<br />

(declare (speci<strong>al</strong> .leaves.»<br />

(fi nd-a 11-1 eaves-l tree) ; Grovel over the tree<br />

.leaves-<br />

;And r<strong>et</strong>urn the leaves found<br />

} }<br />

(defun find-<strong>al</strong>l-leaves-l (tree)<br />

(declare (speci<strong>al</strong> .leaves-»<br />

(cond «atom tree)<br />

(cond «not (memq tree .leaves-})<br />

(s<strong>et</strong>q .leaves- (cons tree .leaves-»}»<br />

(t (find-<strong>al</strong>l-leaves-l (car tree»<br />

(find~<strong>al</strong>l-leaves-l (cdr tree»}»<br />

to demonstrate the common uses· (If the speciat declaration. The declaration in find - <strong>al</strong>l -leaves is<br />

an immediate declaration; it causes -leaves. to be dynamic<strong>al</strong>ly bound. In find-aU-leaves-1. it<br />

is a pervasive declaration which says that the references to .Ieaves. within that function are<br />

references to the speci<strong>al</strong> v<strong>al</strong>ue of -leaves.. It" hilppens that in find-<strong>al</strong>l-leaves-1. both the<br />

interpr<strong>et</strong>er and compiler would figure out that the references to .Ieaves. would have to be<br />

speciaJ references because they arc "free" references (there is no lexic<strong>al</strong>ly apparent binding).<br />

however the compiler would issue a warning about this. So. that declaration serves to teU the<br />

compiler, the interpr<strong>et</strong>er. and a reader of the code, that the references to .Ieaves. in find-aUtrees<br />

-1 are deliberately speci<strong>al</strong>.<br />

6.1.2 Declarations Affecting Variable Bindings<br />

Here arc the other declarations <strong>NIL</strong> accepts which associate with variables. being bound. It is<br />

an error for a variable to be specified in one of them. when it is not being bound by the<br />

construct the declaration is, associated with.<br />

(i gnore VQ,../ va,...2 ••• va,..n)<br />

This says that the specified variables. <strong>al</strong>though bound by the associated construct, are not actu<strong>al</strong>ly<br />

used. Its purpose is to tell the <strong>NIL</strong> compiler that you are aware that you wiU not ever reference<br />

the v<strong>al</strong>ues of those variables; otherwise, it might warn you that the variable is never referenced.<br />

One common use for this declaration . is for arguments to functions which are given, but<br />

(possibly because of an early Slate of development) not used. For instance,<br />

(defun program-d<strong>et</strong>erministic-p (program)<br />

(declare (ignore program»<br />

nil)<br />

which defines a function which takes a program as an argument, and r<strong>et</strong>urns t if it can be<br />

d<strong>et</strong>ennined that is d<strong>et</strong>cnninistic and it is, nit otherwise. The other common use is with speci<strong>al</strong><br />

binding constructs where som<strong>et</strong>hing must· be specified pOSition<strong>al</strong>ly, but what is obtained from that<br />

position is not needed. For instance,<br />

(defun mod (x y)<br />

(multiple-v<strong>al</strong>ue-bind (quo rem) (floor x y)<br />

(declare (ignore quo})<br />

rem) )<br />

which is how mod could" be defined; see page 81-mod is defined to be the second v<strong>al</strong>ue<br />

MC:<strong>NIL</strong>MAN:DCLS 31<br />

23-DEC-83<br />

- "<br />

.. _ ,_ C",<br />

., or ~ , ~ •<br />

• " ~,<br />

~. ~, ",."<br />

-" - .' - .". :. ." -;. .:,' • " • ' - .' > - - , "-" '", "'"' " ~,


_'<br />

.-,,:'<br />

- .' 0 ':'. ~;".<br />

y ''- • _ ,- _". •<br />

<strong>NIL</strong> Manu<strong>al</strong> 45 Loc<strong>al</strong> Declarations<br />

r<strong>et</strong>urned by the COMMON USP floor function.<br />

In the current <strong>NIL</strong> compiler. a variable declared with ignore but actu<strong>al</strong>ly referenced. will<br />

probably °not be d<strong>et</strong>ected. and will produce (erroneous) code just as if the variable had never<br />

been bound<br />

(type type var-I var-2 .•• var-n)<br />

(type var-I var-2 •.. var-n )<br />

These declare that the specified variables are of the type type. For the first fonn. type may be<br />

o<br />

any v<strong>al</strong>id type specifier (see section 4.1.1. page 16). For the second. only certain type specifiers<br />

which are symbols will be recognized: in the current <strong>NIL</strong> compiler. only fixnum is recognized.<br />

(The symbols flonum and notype are rccognized for MACLISP compatibility.)<br />

The current <strong>NIL</strong> compiler simply recognizes this declaration and throws it away.<br />

6.1.3 Declarations Affecting ~ompilation Strategies<br />

These de(' lrations make no statements about the program, so (in the absence of compiler<br />

bugs!) can have no effect other than efficiency on programs which are correct.<br />

(optimize (qu<strong>al</strong>ity-/ v<strong>al</strong>ue-I) (qu<strong>al</strong>ity-2 v<strong>al</strong>ue-2) ••• )<br />

The optimize declaration is used to ten the compiler how it should go about making decisions<br />

when it compiles code, in" a fairly gener<strong>al</strong> way; there are four different qu<strong>al</strong>ities which may be<br />

specified. Each may take on a v<strong>al</strong>ue which is an integer from 0 to 3 (inclusive); 0 says that that<br />

aspect should be discounted compl<strong>et</strong>ely. and 3· says that it is very important. The default v<strong>al</strong>ue<br />

for each is 1. The qu<strong>al</strong>ities are:<br />

speed<br />

Speed is of the essence. The compiler should try harder to make the code run faster.<br />

Obviously. doing so is going to have to trade off against at least one of the other<br />

following qu<strong>al</strong>ities-if it did not, then the compiler wouldn't have to make a choice.<br />

space<br />

This qu<strong>al</strong>ity attempts to quantify for the compiler how important compactness of code is.<br />

saf<strong>et</strong>y<br />

This attempts to quantify to the compiler how important the "saf<strong>et</strong>y" of the code is. The<br />

exact meaning of this is somewhat hazy; the <strong>NIL</strong> compiler takes it to mean that operations<br />

should d<strong>et</strong>ect erroneous inputs and situations when possible. or barring that, at least do<br />

things so that they might be less likely to trash your environment irrevocably in such a<br />

situation.<br />

compilation-speed<br />

The speed of compilation. In the <strong>NIL</strong> compiler, specifying a higher v<strong>al</strong>ue for this qu<strong>al</strong>ity<br />

will make it do a bit less in the way of minor or speci<strong>al</strong>-case optimizations which do not<br />

affect program operation <strong>al</strong>l that much, individu<strong>al</strong>ly.<br />

What the <strong>NIL</strong> compiler does for the various v<strong>al</strong>ues of these qu<strong>al</strong>ities is discussed in section 24.2,<br />

page 246.<br />

MC:<strong>NIL</strong>MAN;DCLS 31<br />

, .-. --<br />

-. • • < <<br />

. . ~ ~,' ~~ -' ~ . ~ ~ _ .<br />

• • _ ~ ~'_ .... - ,.. > ~ _ ~.;o _ '. r _<br />

"_


Proci&un.lliUlls: Glob4t1 I >edarations 46<br />

Nil. Manu<strong>al</strong><br />

( i n 1 i ne jUllc/iowl JUIlC/iOIl-2 ••• )<br />

(notinline jUllction-1 jUllctioll-) ••• )<br />

Theintine declaration says that the compi1er should attempt to code cans to the named functions<br />

'·in Hne"-that is. essenti<strong>al</strong>ly codc the body of thc function in placc of the c<strong>al</strong>l to the function.<br />

The notinline declaration says that this should not be done. Becausc the SIL compiler nonna11y<br />

in line-codes anything it knows how to. the inline declaration is re<strong>al</strong>ly only useful in <strong>NIL</strong> to<br />

shadow a notinline declaration.<br />

There arc a couplc· reasons why one might specify that a function not be coded inline. First.<br />

things like trace (page 220) c~m only '·trace" the function c<strong>al</strong>t if there actu,dly is a function c<strong>al</strong>l.<br />

S~cond. inlinc compilation. while il does not <strong>al</strong>ways eliminate error checking, sum<strong>et</strong>imes<br />

aggravates dehugging hy causing an error to be sign<strong>al</strong>led other than where it w(}uld ha\'c been in<br />

the interpr<strong>et</strong>ed code. ur (worse y<strong>et</strong>) causes some other error to happen.<br />

The compiJer is free to ignore the inline declaration: if it docs not know how to inline a<br />

function. it simply cannot do so. However. anything declared notinline will be compiled as a<br />

function c<strong>al</strong>l. It is an erfor to specify this for a specia1 fonn. e.g.. condo and it is prubably<br />

meaningless and ~I'! addition an error to do so for a macro~<br />

It is important to note that many functions in !\IL provide an intennediate possibility b<strong>et</strong>ween<br />

compl<strong>et</strong>e open-compilation without error checking. and c<strong>al</strong>ling the regular function: there is a<br />

large body of speci<strong>al</strong> subroutines in the <strong>NIL</strong> kernel which have caHing sequences optimized for<br />

how the compiler can compile c<strong>al</strong>ls to them. but which do error checking. This means that. for<br />

c<strong>al</strong>L cllthough one docs lose trace "lpabiJity. and the visibility of the function can on the stack<br />

when it is examined with the debugger. Wh<strong>et</strong>her such routines code as these "minisubr" c<strong>al</strong>ls or<br />

are compl<strong>et</strong>ely coded inline without error checking (where that is possible) is gener<strong>al</strong>1y controned<br />

by the optimize declaration. The d<strong>et</strong>ailed low· level specifics of this are discussed in section 24.2.<br />

page 246.<br />

6.2 Proclamations: Glob<strong>al</strong> Declarations<br />

Often one wants to make . declarations "glob<strong>al</strong>ly". For instance. to assert that a panicular<br />

variable is· <strong>al</strong>ways speci<strong>al</strong>, to s<strong>et</strong> an optimization param<strong>et</strong>er for the compilation of entire file. <strong>et</strong>c.<br />

The function proclaim is used for this.<br />

procl aim &rcst del-specs<br />

Each del-spec is a declaration specification (just like for decfare-see the beginning of the<br />

previous section). However. it is put into force "glob<strong>al</strong>ly". Many of the decJarations one<br />

may m.ake with proclaim are similar to those onc might loc<strong>al</strong>ly declare with declare,<br />

. however their semantics arc different because of their glob<strong>al</strong> nature. They are listed<br />

below.<br />

Note: it seems the CO\1MON LISP proclaim only takes one dd-spec argument?<br />

It is imponant to nole that proclaim subsumes previous usage of declare which was not in a<br />

speci<strong>al</strong> position (as described in the previous section). While declare in <strong>NIL</strong> is still accepted in<br />

ttabnonn<strong>al</strong>" positions (and might continue to be indefinitely for MACUSP compatibility), usc of<br />

MC:NII.MAN:DCLS 31<br />

" . - ~.... ~ , ~~<br />

, ,<br />

, '. :',' '. .~:... -. • , '-. ~', ' : . - .' • , -.' -', " >~.' ,,-"'"' ~ -.. .• ,. ~,; "-'.- ,-~


Nil. Manu<strong>al</strong> 47 Declaring tlle Types of Fonns<br />

proclaim is recommended to emphasize the nature of the declaration.<br />

proclaim ev<strong>al</strong>uates its argument.<br />

Also. remember that<br />

The ~IL compiler will recognize caIls to proclaim at top-level within a file. and. if the<br />

argument to it is constant (Le., it is quoted). put that declaration in force for the remainder of<br />

the compilation, in addition to outputting it to' the file: that it, it is as if it g<strong>et</strong>s wrapped by<br />

(ev<strong>al</strong>-when (ev<strong>al</strong> compile load) ... ) (see ev<strong>al</strong>-when, page 25).<br />

(speci<strong>al</strong> l'a~1 var-2 .•. \lar-Il)<br />

A speci<strong>al</strong> proclamation not only glob<strong>al</strong>ly declares that <strong>al</strong>l of the named variables should be<br />

referenccd speci<strong>al</strong>. but <strong>al</strong>so that <strong>al</strong>l bindings should be speci<strong>al</strong>. Howc\cr. one nonn~ll1y uscs<br />

defvar (pagc 24) without an initi<strong>al</strong>ization fonn to glob<strong>al</strong>ly dcchtfC a variahle speci<strong>al</strong>. or. whcn<br />

giving an initi<strong>al</strong>ization. uses defvar or defparam<strong>et</strong>er.<br />

(type type vor-l var-2 •.• \'or-Il)<br />

Syntactic<strong>al</strong>ly. this is the same as the rcgular type dcclaration. Howcvcr. the type information is<br />

associatcd with the speci<strong>al</strong> \'<strong>al</strong>l!~s of the variables. not with lcxic<strong>al</strong>ly bound variah1es of thc same<br />

names. so this is typic<strong>al</strong>ly p;~'red with a speci<strong>al</strong> proclamation. or with defvar (pagc 24),<br />

defparam<strong>et</strong>er (page 24). or defconstant (page 24).<br />

~Il..<br />

of course, ignores this right now.<br />

6.3 Declarin2 the Types of Forms<br />

Often one might want to associate type infonnation with a fonn. wherc there is no variable '<br />

being bound. The the speci<strong>al</strong> form <strong>al</strong>lows one to do this.<br />

the type-specifier [onn<br />

the declares that the v<strong>al</strong>ue r<strong>et</strong>urned by the ev<strong>al</strong>uation [oml is of the type type-specifier.<br />

Were the compiler to do nifty things with type constraining. use of this could greatly<br />

enhance its ability to optimize: currently. the compiler gener<strong>al</strong>ly throws away the type<br />

information. with the exception of a rare misguided speci<strong>al</strong>-form which explicitly looks for<br />

a the form. The <strong>NIL</strong> interpr<strong>et</strong>er. however. does verify that the r<strong>et</strong>urned v<strong>al</strong>ue is of the<br />

specified type.<br />

The type-specifier may be any v<strong>al</strong>id type specifier. and <strong>al</strong>so may be of the fonn<br />

(v<strong>al</strong>ues ~pespe~l QP~pe~2 ... ~pespe~n)<br />

in which case the r<strong>et</strong>urned v<strong>al</strong>ues must be of the specified types.<br />

MC:<strong>NIL</strong>MAN:DCLS 31<br />

23-DEC-83


Sequences 48 NII~ Manu<strong>al</strong><br />

7. Sequences<br />

A sequence is considered to be either a list or 'a vector (which is by definition a onedimension<strong>al</strong><br />

array). <strong>NIL</strong> supports a number of operations on sequences, which may be applied<br />

equiv<strong>al</strong>ently to lists. vectors. strings. and bit-vectors.<br />

Many sequence function take start and end arguments to delimit some subpart of the sequence<br />

being operated on. As a gener<strong>al</strong> rule. the slart is inclusil'f.'. and the end is exclusive: thus the<br />

length of the subsequence is thc difference of the elld and the starl. The start typic<strong>al</strong>ly defaults<br />

to O. and the end to the length of the sequence. Also.' the end. where it is an option<strong>al</strong><br />

~.rgurnent. may be explicitly specified as nil. ,md will sti1l def4111lt to' the length of the sequence.<br />

Thus.<br />

( fin d ile111 sequellce)<br />

searches the entire sequence.<br />

(fi nd ilem sequell('(' : start 5)<br />

and<br />

( fin d ilel11 sequence :! ~:-. art 5 : end nil)<br />

search from clement numher 5 onward.<br />

(find ilem sequ('lIc(' :end 5)<br />

checks the first five clements, and<br />

(find ile111 sequence :start 5 :end 10)<br />

searches the subsequence (which has a length of 5) which consists of the clements with indices 5,<br />

6, 7, 8. and 9~<br />

Functions which operate on two sequences gener<strong>al</strong>ly take the start and' end for each of the<br />

sequences separately: these are kcyworded arguments named :staru and :end1 to specify the<br />

subsequence of the first sequencc. and :start2 and :end2 to specify the subsequence of the second<br />

scqucnce. See, for insL1ncc. replace (page 52).<br />

Many sequence functions (and many other functions) pcrfonn comparisons of various sorts.<br />

For instance. find searches for an item in a sequence. (find item sequence) looks for an· element<br />

of sequence which is eql to item, and r<strong>et</strong>urns that element. The particular test used may be<br />

customized: a different test function may be spccified by use of the :test key worded argument, as<br />

in<br />

(find item sequence :test #'equ<strong>al</strong>)<br />

which uses equ<strong>al</strong> rather than eql. The sense of the test can be reversed by using :test-not<br />

instead of :test:<br />

(find item sequence :test-not #'equ<strong>al</strong>)<br />

r<strong>et</strong>urns the first clement of sequence which is not· equ<strong>al</strong> to item.<br />

Often. what one wants to compare against is not each element of the sequence. but some<br />

subpart of each clement For this, rather than composing a new :test function. one may specify<br />

a:key function. For instance,<br />

(fi nd ilem sequence : key # tear)<br />

will r<strong>et</strong>urn the first clement of sequence whose car is eql to item. This may <strong>al</strong>so be used with<br />

:test or :test-not. Note that the key function is only applied to clements extracted from<br />

sequences. ncver to things like the item argument to find.<br />

MC:NII.MAN;SEQUEN 19<br />

2J-DEC-83<br />

~ • '- _' ~ • _ ...... :- .-,o;.~ ~. • ~,-<br />

, ~ "- " ~ ~ - - ~ . -<br />

__ . ,.,>._. , " ".;';,,"";:"".' _"";~;~:.,~:.-,~,, , .... ,.:,_ .. -:.:. ,.-. -~'~ ... ~~~.-~J.>~. '-'':''''::'~' , .... , .. - '.' """.:_.:';,


2<br />

fi .-<br />

Nil. Manu<strong>al</strong> 49 A"e~sing Sequences<br />

Another c1ass of functions do "searching" by means of a unary predicate. These functions<br />

invariably come in pairs: one in which the test is satisfied if the test function r<strong>et</strong>urns a non-nil<br />

v<strong>al</strong>ue. and one in which the test is satisfied if the test function r<strong>et</strong>urns nil: for instance.<br />

position-if and position-if-not. and assoc-if and assoc-if-not. Often these functions <strong>al</strong>so take<br />

a :key keyworded argument <strong>al</strong>so: if that is specified. then that function is applied to the datum<br />

being tested and the result given to the test function. For the sequence functions. the datum is<br />

the clement of the sequence being examined.<br />

Fin<strong>al</strong>1y. for things which go grovelling through sequences sequenti<strong>al</strong>ly. one may specify the<br />

direction by usc of the :from-end keyworded argument. which if not nil means that the result<br />

will he as if the subsequence was processed from the higher to tower indices. rather than from<br />

lower to higher. Unless explicitly specified f()f a particular function. it may nul be depended on<br />

that the sequence is actu<strong>al</strong>1~ processed in that order. only tll<strong>al</strong> the end result is the same: for this<br />

reason. it is gener<strong>al</strong>ly a bad idea if the comparison or key functions have any side effects. or<br />

depend on the ordering of the clements on which they arc c<strong>al</strong>led.<br />

7.1 Accessing Sequences<br />

81 t sequence index<br />

This is the gener<strong>al</strong> sequence access function. It r<strong>et</strong>urns the indexth clement of sequence:<br />

the index is taken to be 7.ero-origined. This will work gener<strong>al</strong>ly on lists. vectors. strings<br />

(which are by definition vectors anyway). <strong>et</strong>c. One may modify an clement of a sequence<br />

hy 11sing s<strong>et</strong>f For inst~T'!("e.<br />

(s<strong>et</strong>q V (make-vector 10»<br />

=> #(nil nil nil nil nil nil nil nil nil nil)<br />

(s<strong>et</strong>f (e1t v 6) 'fool<br />

=> foo<br />

And now,<br />

v => #(ni1 nil nil nil n11foo nil nil nil nil)<br />

It is an error for index to be negative, or not less than the length of sequence as defined<br />

by length. This' means that it is an error to index p~ss the end of a list (in this elt<br />

differs from nth. page 57). and <strong>al</strong>so in its treatment of vectors with fill pointers (the fill<br />

. pointcr defines the length-to access anywhere within such a vector, use aref (page 103».<br />

1 ength sequence<br />

R<strong>et</strong>urns the length 'of sequence. If sequence is a vector with a fill pointer, the fill pointer<br />

is r<strong>et</strong>urned. In NI~ length will d<strong>et</strong>ect a circular list. and sign<strong>al</strong> an error; in other<br />

imp1ementations. it may fail to tenninate-contrast the definition of list-length, page 59.<br />

If sequence is a list. it is an error for it to not terminatc in nil-in this, length differs<br />

from previous implementations of <strong>NIL</strong>.<br />

MC:<strong>NIL</strong>MAN;SEQUEN 19


Creating New Sequences 50 Nil. Manu<strong>al</strong><br />

7.2 Creating New Sequences<br />

Many functions which create sequences take an argument which is the type of sequence to be<br />

created: it is typic<strong>al</strong>ly caHed the result-type, or perhaps just the type. This may be, in gener<strong>al</strong>. a<br />

type specifier suitable for use with typep, but must of course be a subtype of sequence-that is,<br />

a SUbtype of list or vector. The type of sequence created will be the most specific type of<br />

sequence which is a subtype of that specified type. At this time. the ~IL sequence code has not<br />

been integrated with the 1'11. array type code. so it is possible that complicated type specifications<br />

will not work. The filllowing typcs wi11 <strong>al</strong>ways work: list. string. simple-string. bit-vector.<br />

simple-bit-vector. simple-vector, and vector. vector. which is rcaH), an ahbreviation for the<br />

type specifier (array • (.». i.e.. a one-dinlcnsiomlt array of unspecifiedc1emem-type. will create a<br />

vector of clement-type 1. i.e.. a gener<strong>al</strong> '"ector.<br />

m<strong>al</strong> f •••••• "<br />

Creates a sequence of type reSull-/.lpe (as might be given to make-sequence). and stores<br />

in it the concatenation of aU the clements of sequences. For instance.<br />

(concatenate 'string "foo" "bar" ~baz")<br />

=> "foobarbaz"<br />

(concatenate 'list "foo" "bar" '(1 2»<br />

=> ('\f '\0 '\0 '\b '\a #\r 1 2)<br />

subseq sequence start &option<strong>al</strong> end<br />

R<strong>et</strong>urns a sequence of the same gener<strong>al</strong> type as sequence, containing clements from start<br />

up to (but not including) end.<br />

(Subseq "faa on you" 4) => "on you"<br />

(subseq "faa on you" 4 6) => "on"<br />

(subseq "faa on you" .4 3) => is an error<br />

(subseq tea b c d) 1 3) => (b c)<br />

Note that the result of subseq never shares with the origin<strong>al</strong> sequence. Thus. (subseQ<br />

lisl 5) is not the same as (nthcdr 5 list). In fact. subseq would sign<strong>al</strong> an error in this<br />

case if the list did not have at least 5 elements.<br />

The result of subseq wi11 <strong>al</strong>ways be a simple sequence; if, for instance, sequence is an<br />

adjustable array of element-type string -char and has a fill pointer. the result will just be<br />

a simple string.<br />

MC:NII.MAN:SEQUEN 19<br />

23"DEC-83<br />

~ ~ ~ ~, r-\~ ~<br />

, "<br />

.. , ~ - " ~<br />

~ \- ¥ ....,<br />

• :~,"<br />

"<br />

"" • : ' " ';',," --:~<br />

.-:<br />

,,' " ' .. ~",:..:.:;'. ". '., - - , ' " : - , - '", • - - , •• '~ -<br />

- >


<strong>NIL</strong> Manu<strong>al</strong> 51 Searching through Sequcnccs<br />

copy-seq sequence<br />

Copics thc sequcnce sequence. This might be neccssaryif the rcsult is going to he<br />

modified. for instance. 'Inc result of copy-seq will <strong>al</strong>ways be a simple sequence. as<br />

described undcr subseq.<br />

See <strong>al</strong>so thc map function, page 54. which produces a sequence of the results of applying a<br />

function to the corresponding clements of some input sequences.<br />

7.3 Searching through Sequences<br />

fin d i/{'m SClI1U'I1U' &kcy from-end slar! elld leSI lesl-not kcy<br />

find searches through the specified subsequence of sequencc until it finds an clement which<br />

satisfies the specified comparison ,lgainst item. in which case it r<strong>et</strong>urns th<strong>al</strong> clement: if no<br />

,match is found. find r<strong>et</strong>urns nil. If a non-null from-end argument is specified, then the<br />

result (if there is a match) will be the "rightmost" clement which matches ilem, otherwise<br />

it will be the "leftmost".<br />

fi nd-1f Icsl sequcl1ce &key from-end Slarf cnd key<br />

fin d - 1 f - not lesl scquence &key from-end sian elld key<br />

find - if r<strong>et</strong>urns an clement of the specifed subsequence of sequence which satisfies the<br />

function ICSI. or nil if no such clement is found. If a key argument is specified, then lesl<br />

is c<strong>al</strong>led on the result of c<strong>al</strong>ling key on an clement of the sequence: otherwise. lesl is<br />

c<strong>al</strong>led on the element directly. If a non-null from-Pl1d argument i~ ~pccifiec1, thpn rhp<br />

result will be the rightmost such clement within the subsequence: otherwise. it will be the<br />

leftmost.<br />

find -if-not is similar. but succeeds if the result of c<strong>al</strong>ling test is nil.<br />

pos 1 t 1 on item sequence &key from-end start end test test-not key<br />

If there is an clement of the specified subsequence of sequence which matches item<br />

according to the specified test, then position r<strong>et</strong>urns its index (the index within sequence.<br />

not within the subsequence); otherwise. position r<strong>et</strong>urns nil. If a non-null from-end<br />

argument is specified. then the result is the index of the lefunost element satisfying the<br />

test; otherwise. it is the index of the righunost such element.<br />

pos it ion-if test sequence &key from-end start end key<br />

position-if-not test sequence &key from-end start end key<br />

pOSition-if r<strong>et</strong>urns the index of an element within the specified subsequence which<br />

satisfies the test function lest. If key is specified, it is a function c<strong>al</strong>led on the element of<br />

the sequence. and that result is given to test instead of the clement itself. If a non-null<br />

from-end argument is specified. then the index will be of the rightmost such clement:<br />

otherwise. of the leftmost. If no such clement is found in the subsequence, nil is<br />

r<strong>et</strong>urned. As with position and <strong>al</strong>l similar functions, the index is the index within<br />

sequence. not within the subsequence.<br />

position-if-not is similar, but succeeds if the result of c<strong>al</strong>ling test is nil.<br />

MC:NII.MAN:SEQUEN 19<br />

23-DEC-83


. Qig~ .. h4iWJJllU. • .i a LJ 71<br />

Misccllmlcous Opcratiuns on Sequences 52 Nil. M411lu<strong>al</strong><br />

count ilem sequence &key from-end Slarl elld I('SI tl'SI-Il(J/ key<br />

count rcturns the count of clements within the specified subsequence of sequence which<br />

satisfy the specified comparison against item. The test function may depend on the order<br />

in which the clcments arc processed: if a non-null from-end argument is specified .. then<br />

the clements will be processed from right, to left (Le.•<br />

decreasing· indices); otherwise. from<br />

left to right (increasing indices). As usu<strong>al</strong>, the first argument to the test is item. and the<br />

second is the clement of sequence if no key is specified, otherwise the result of c<strong>al</strong>ling key<br />

on the elemenl<br />

count-1 f Irsl srqucl1ce &key from-cnd Slar! end key<br />

count-if-not Irsl srqurll('(' &key Ji-om-clld slart elld key<br />

count-if rcturns the count of tile element~ of suhscquence which S4uisfy thc unilry<br />

predicate lesl. If no kcy is specificd. lest is caned on tile cIement~ of the subsequence;<br />

otherwisc. it is c<strong>al</strong>led on the result of applying key to ench clement If a non-null fromclid<br />

argument is specified. tilen tile c1ement'i are processed from right to left (decreasing<br />

indices), otherwise from left to right.<br />

count-if-not is similar. but reverses the sense of lesl.<br />

7.4 l\liscellaneous Operations on Sequences<br />

reverse sequence<br />

R<strong>et</strong>urns a copy of sequence. with the clement, in the op!,ositc order_<br />

nreverse sequence<br />

Reverses sequence, destructively; it does not create a copy. Note that if sequence is a list.<br />

one should <strong>al</strong>ways use the r<strong>et</strong>urn v<strong>al</strong>ue of nreverse: that is. do som<strong>et</strong>hing like<br />

(s<strong>et</strong>q 1 (nreverse 1»<br />

rather than just<br />

(nreverse 1)<br />

This is in genera] true for <strong>al</strong>l destructive list operations. such as sort and delQ. The<br />

reason is that <strong>al</strong>though the cons cells of the input list are reused. the pointer r<strong>et</strong>urned is<br />

not necessarily the same as the origin<strong>al</strong>ftfirst tt cons of the lisL<br />

fill sequence element &key start end<br />

Replaces the elements of sequence with element, from start (default 0) up to end (default<br />

length of the sequence).<br />

(s<strong>et</strong>q a '(0 1 2 3 4 5 6»<br />

(fill a nil :start 2 :end 4)<br />

=> (0 1 nil nil 4 5 6)<br />

And now,<br />

a => (0 1 nil nil 4 5 6)<br />

rep 1 ace sequence! scquencel &key starl! end! s1art2 endl<br />

Replaces the clements of the specified subsequence of sequence} by the elements of. the<br />

specified subsequence ofsequelice2.<br />

MC:NII.MAN:SEQUEN 19<br />

23-DEC-83<br />

. ~ , ' -<br />

.' > ":: " ' , :'.:: :., . ..: ,~>.::,.;' .",: :,""c..'" ,'" "" "


Iteration over Sequences 54<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

substitute-1f nrw lrsl spquellce &key from-end Slart end key ('ou",<br />

substitute-if-not new lest sequence &key j;om-end slart end key COUIlI<br />

Similar. by extension.<br />

nsubst1tute new old sequence &1cey /rom-elld slart end test les/-not key count<br />

The destructive version of substitute; sequence is modified.<br />

nsubstitute-1f new lest scquence &key /rom-e1ld start end key counl<br />

nsubs t 1 tute-1f-not new test sequellce &kcy /rom-el.ld start end key count<br />

Similar.<br />

7.5 Iteration over Sequences<br />

The fi)lIowi,ng functions iterate a user-specified function over one or more sequences in various<br />

ways.<br />

map rcsu/t-typc junctioll &rest sequellt~es<br />

'111is is the gener<strong>al</strong> sequence mapping function. Nute that this is different from the<br />

MAC'l.ISP and LISP MACHINE LISP map function. which is renamed to mapl by COMMON<br />

USP.<br />

The result is a new sequence of type result-type (see section 7.2. page 50). containing the<br />

results of applying jUliction to the clements of sequences. There must be at least one<br />

srqllenee specified: junction g<strong>et</strong>s as many arguments as there are sequences-first it g<strong>et</strong>s<br />

c<strong>al</strong>led on <strong>al</strong>l of the first (index 0) clements. then on ,,11 the second clements. <strong>et</strong>c. The<br />

iteration tenninates when the end of any of the sequences is reached. so the result will<br />

have the same length as the shortest input sequence.<br />

(map 'list #'cons "abc" '(a bed e f»<br />

=> (#\a . a) (#\b • b) (#\c • c»<br />

If result-type is list. and the input sequences are <strong>al</strong>l lists. then this is effectively the same<br />

as mapcar (page 31).<br />

some predicate &rest sequences<br />

some applies the function predicate to the corresponding elements of sequences (of which<br />

there must be at least one), in order. If the result of some application is not nil, then<br />

some immediately tenninates the iteration and r<strong>et</strong>urns that v<strong>al</strong>ue; if <strong>al</strong>l the applications<br />

r<strong>et</strong>urned nil. some r<strong>et</strong>urns nil.<br />

The predicate may depend on being c<strong>al</strong>led on the elements of the sequences in order.<br />

Only as many elements as there are in the shortest sequence are processed.<br />

The effect of this may <strong>al</strong>so be obtained by use of the thereis clause in the loop macro<br />

(page 144).<br />

MC:<strong>NIL</strong>MAN:SEQUEN 19<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 53 Miscellaneous Operations on Sequences<br />

(s<strong>et</strong>q v (make-sequence 'vector 10»<br />

=> #(nil nil nil nil nil nil nil nil nil nil)<br />

(replace v '(1 2 3 4 5 6»<br />

=> #(1 2 3 4 5 6 nil nil nil nil)<br />

v => #(1 2 3 4 5 6 nil nil nil nil)<br />

The number of elements transfercd is the minimum of the lengths of the two<br />

subsequences, i.e.,<br />

(min (- end! startl) (- end2 start2»<br />

remove ilrl11 srquence &key /rom-end slart elld leSI tesl-lIol key COUllt<br />

remove r<strong>et</strong>urns a copy of srquem'c of Ule S.lI11C gener<strong>al</strong> type. except that clements within<br />

Ule specified suhsequence which match ilem according to the specified test arc not copied.<br />

If Ule COUllt argument is -specified. then it should he a non-negative integer which limit'!<br />

the numher of matching element~ which g<strong>et</strong> "ignored": jf it is not specified. <strong>al</strong>l matching<br />

-clements within the specified subsequence wHl be missing from ule result. The from-end<br />

flag is only re<strong>al</strong>ly meaningful if a COUIlI is specified: if a non-null from-end is specified.<br />

then the rightmost COUIII c1ement~ of the specified subsl~quence will be missing from the<br />

resul~ otherwise the leftmost.<br />

remove-if tesl sequence &key /rom-end slarl elld key count<br />

remove-if-not tesl sequence &key /rom-end slarl end key COUllt<br />

Like <strong>al</strong>l similar extensions.<br />

de 1 <strong>et</strong>e f!rn: ~rqur::('[' &kcy from-end start end test lest iwi key COUiii<br />

'J11is is the destructive version of remove. q. v.: it will attempt to use sequellce to<br />

construct its resu It The result mayor may not be eq to sequence. and sequence mayor<br />

may not be actu<strong>al</strong>ly modified to produce the result: <strong>NIL</strong> will attempt to do this the "best<br />

way" it can. For this reason. del<strong>et</strong>e should ullly be used for v<strong>al</strong>ue, never strictly for<br />

effect.<br />

del<strong>et</strong>e will succeed in side-effecting sequence to produce its result jf sequence is (1) a list,<br />

(2) an adjustable vector of any type, or (3) a vector with a fin pointer. The result is still<br />

not guaranteed to be eq . to sequence.<br />

de 18 t 8 -1 f lesl sequence &k ey from-end slart end key count<br />

del<strong>et</strong>e-if-not les/ sequence &kcy /rom-end start end key count<br />

Similar, by extension.<br />

subst 1 tute new old sequence &key from-end slart end lesl test-not key count<br />

substitute r<strong>et</strong>urns a new sequence in which the elements within the specified subsequence<br />

matching old according to the specified test have new substituted. While substitute does<br />

not modify sequence, the result may share with sequellce; in particular, if sequence is a<br />

list, the result may share a tail.<br />

If a count argumcnt is specified. then this is a non-negative integer which limits the<br />

number of substitutions madc. In this case. specifying a non-null from-end argument<br />

causes the rightmost COUIlI clements matching old to undergo substitulion. otherwise the<br />

leftmost.<br />

MC:<strong>NIL</strong>MAN;SEQUEN 19<br />

23-DEC-83


<strong>NIL</strong> Manua} 55 Sorting Sequences<br />

every predicate &rest sequences<br />

l.ike some. but r<strong>et</strong>urns t if thc result of applying predicate to the clements of sequences is<br />

ncvcr nil: if some app1ication of predicate is nil. then every terminatcs immediately and<br />

rcturns nil.<br />

The effect of this may <strong>al</strong>so be obtained by use of the <strong>al</strong>ways clause in the loop macro<br />

(page 144).<br />

not any pr('dicate & rest sequences<br />

R<strong>et</strong>urns t if the rcsult of applying the function predicate to the corrcsponding clements of<br />

scqU(,IIC(,S is <strong>al</strong>w,lYs nil: if the result of that application is not nil. then notany<br />

immediately tenninates thc itcration and r<strong>et</strong>urns nil.<br />

The cffect of this may <strong>al</strong>so be obtaincd by usc of the never clause in the loop macro<br />

(pagc 144).<br />

notevery predicate &rcst sequences<br />

If the result of some application of predicate to the corresponding clements of sequences is<br />

nil. then notevery tenllinates its iteration and r<strong>et</strong>urns t: otherwise. it r<strong>et</strong>urns nil.<br />

7.6 Sorting Sequences<br />

sort sequence predicate &k~y key<br />

This is the (,OMM01' LISP sort function: when it is used without a key. it is MACI.lSP<br />

compatible.<br />

sequence is destructively sorted according to thc predicate predicate. which receives two<br />

arguments and should r<strong>et</strong>urn a non-null v<strong>al</strong>ue only if its first argument is strictly less than<br />

its second argument. If key is spccified. then it is a function of one clement which is<br />

applied to the sequence element before being passed on to the predicate.<br />

For MACLISP compatibility, if sequence is a list. then the sort is stable; equiva1ent pairs of<br />

items (those where the two keys are neither strictly less than each other) remain in their<br />

origin<strong>al</strong> order. When sequence is a vector, a quicksort <strong>al</strong>gorithm is used.<br />

sortcar sequence predicate<br />

This is provided for MACLISP compatibility. It is just like<br />

( so r t sequence predicate : key II' c'a r )<br />

stab le-sort sequence predicate &kcy key<br />

Like sort. but guarantees that the sort will be stable (sec sort). If sequence is a vector,<br />

thcn a bubble sort is used.<br />

MC:NII.MAN:SEQUEN 19<br />

23-DEC-83


Lists<br />

8. Lists<br />

Note <strong>al</strong>so consp (page 18). listp (page 18).<br />

S6<br />

Nil. Manu<strong>al</strong><br />

8.1 Creating, Accessing, andl\1odifying List Structure<br />

car COilS<br />

cdr cons<br />

c ...• r cons<br />

'II dcfincsaJt compositions of car ,md cdr up to four levels deep; Illr insk1nce. (cddar<br />

COilS) is equiv<strong>al</strong>ent to (cdr (cdr (car elms»).<br />

Actu<strong>al</strong>ly. COilS may be either a cons or nil: the car and cdr of nil arc <strong>al</strong>wa)'s nil.<br />

Nonn<strong>al</strong>ly in <strong>NIL</strong> car. cdr. and their compositions compile into speci<strong>al</strong> subroutine cans<br />

into the !'Il. kernel which do error check~ng. but arc much faster than function ca11ing.<br />

Directing the compiler to produce faster code by usc of the Sf eed qu<strong>al</strong>ity in the optimize<br />

declaration will cause <strong>al</strong>l of these accesses to be compl<strong>et</strong>ely inHne coded, witht}lu<br />

checking: sec section 24.2. page 246. (In <strong>NIL</strong>. car and cdr each Like only one<br />

instruction. )<br />

AlI of these functions may be used with s<strong>et</strong>f in order to update the panicular component<br />

of cons.<br />

rp laca ('OilS new-car<br />

rplacd cons new-cdr<br />

rplaca modifies the car of COilS to be flew-car, and r<strong>et</strong>urns cons: rplaca modifies the<br />

cdr. Sec <strong>al</strong>so s<strong>et</strong>f (section 5.9, page 38) which can be used to update any of the above<br />

car I cdr references.<br />

These functions, and the use of s<strong>et</strong>f with car, cdr. and mends. are norm<strong>al</strong>ly coded by<br />

the <strong>NIL</strong> compiler as speci<strong>al</strong> subroutine caUs into the <strong>NIL</strong> kernel which do argument<br />

checking. but are faster than function c<strong>al</strong>ls. Use of the speed qu<strong>al</strong>ity with the optimize<br />

declaration may override this; see section 24.2, page 246.<br />

f1 rst list<br />

second lisl'<br />

th 1 rd lisl<br />

fourth lisl<br />

fifth lisl<br />

sixth Iisl<br />

seventh lisl<br />

eighth lisl<br />

ninth lisl<br />

tenth lisl<br />

car, cadr, ctc. lbese may <strong>al</strong>l be used with s<strong>et</strong>f.<br />

MC:NII.MAN:LIST 37<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 57 Creating. Accessing, and Modifying Lisl. ..<br />

Note that the names of these functions use one-origin indexing:<br />

(third x) (nth 2 x)<br />

rest list<br />

cdr. This may be used with s<strong>et</strong>f.<br />

nth index list<br />

R<strong>et</strong>urns the illdextl1 clement of list. zero origined. Note <strong>al</strong>so tl1at this takes its arguments<br />

in a different order than 'elt (and other more speci<strong>al</strong>ized sequence accessors).<br />

If illt/ex is not less than 111e length of lisl. nth r<strong>et</strong>urns nil by an<strong>al</strong>ogy to car and cdr. In<br />

111is it <strong>al</strong>so differs from elt.<br />

nthcdr mimes list<br />

, Relurl1S list after mimes cdrs have been taken on it.<br />

Note <strong>al</strong>so tl1e t reader-macro (section 20.1.1. page 216). which is convenient for creating list<br />

structure in template form. especi<strong>al</strong>ly if large portions of it are constant. and push (page 38) and<br />

pop (page 38) which can be lIsed lO maintain a list in FIFO fonn in an arbitrary s<strong>et</strong>fable place.<br />

cons x y<br />

Makes a cons whose car is x. and whose cdr is y.<br />

ncons x<br />

Equiv<strong>al</strong>ent to (cons x nil).<br />

xcons x y<br />

"Exchanged" cons. Equiv<strong>al</strong>ent to (cons y x). This function is not nonn<strong>al</strong>ly used~ it is<br />

inherited from MACLISP. where its existence is mainly for me benefit of me compiler in<br />

rewriting c<strong>al</strong>ls to list into c<strong>al</strong>ls it could chain tog<strong>et</strong>her the computations of b<strong>et</strong>ter:<br />

(list x y z)<br />

==> (xcons (xeons (ncons z) y) x)<br />

11 s t &rcst elements<br />

R<strong>et</strong>urns a freshly created list of its arguments.<br />

(list) => nil<br />

(list 'x) => (x)<br />

(list 'x 'y) => (x y)<br />

11 st. first-thing &rest other-things<br />

Sort of like list. but the last argument to list. is used as the cdr of the fin<strong>al</strong> cons.<br />

instead of nil. Alternatively. it may be thought of as many nested conses:<br />

(list- 'a) => a<br />

(list. 'a 'b) => (a. b)<br />

(list. 'a 'b 'e) => (a b . e)<br />

(list- fa 'b nil) => (a b)<br />

MC:<strong>NIL</strong>MAN:LIST 37<br />

23-DEC-83


Creating, Accessing. and Modifying List .• 58 Nil. Manu<strong>al</strong><br />

make-l1 st size-of list &key il1i1i<strong>al</strong>-elemelll<br />

Creates a list of nils size-offisl lung. whose clemcnl~<br />

nil).<br />

arc inili<strong>al</strong>-elemeflf (which defaults to<br />

append &rcst lisls<br />

(append x y) r<strong>et</strong>urns a list which has first <strong>al</strong>l of the elements of x, fol1owed by <strong>al</strong>l of<br />

the clements of y; for instance.<br />

(append '(a b) '(x y» => (a b x y)<br />

The subpart of this list (in the example. the cddr) is the origin<strong>al</strong> last argument to<br />

append: append never copies its last argument.<br />

(append x )' z)<br />

==> (append x (append y z»<br />

When given une argument, append r<strong>et</strong>urns that argument: with no arguments, it r<strong>et</strong>urns<br />

nil.<br />

If just copying a list is desired, it is stylistic<strong>al</strong>ly b<strong>et</strong>ter to usc (copy-list /is/) (page 59)<br />

rather than (append list nit).<br />

revappend list I Iisl!<br />

This is like (append (reverse lisll) !ist!). but is more effident because it only has to<br />

make one pass over listl.<br />

last Iisl<br />

RNllrn, rhl' l~~t (,one; of lis, (!!!H th~ last e!('m~nt!). un!~ss lis! i~ nil. in ',I,'hkh c~ze it<br />

r<strong>et</strong>urns nil. In r\1L. last de<strong>al</strong>s properly with a non-nun last cdr of /isl. The only noncons<br />

it will accept as an argument howcyer is nil.<br />

(last '(1 2 3 4 5» => (5)<br />

(last '(a b . e)} => (b. c)<br />

(last nil) => nil<br />

nco n c &rest lists<br />

Joins tog<strong>et</strong>her <strong>al</strong>l of the lists by destructively modifying them. Specific<strong>al</strong>ly, for each of<br />

the lists which is not nil~ the fin<strong>al</strong> cons (as might be r<strong>et</strong>urned· by last) is modified by<br />

rpJacd to be the next list<br />

(s<strong>et</strong>q 11 '(a b»<br />

(s<strong>et</strong>q 12 '(x .v»<br />

(ncone 11 12) => (a b x y)<br />

and now,<br />

11 => (a b x y)<br />

One should be careful. however, about using ncone strictly for. effect (i.e., not using the<br />

r<strong>et</strong>urned v<strong>al</strong>ue), because if the first list is nil (the empty list) the desired side-effect will<br />

not occur.<br />

nreconc listl list2<br />

'Ibis is like (ncone (nreverse Jisll) lisI2), but can be faster because it only has to make<br />

one pass over lisil.<br />

~1C:NII.MAN:LIST 37<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 59 Creating. Accessing. and Modifying List ...<br />

list-length list<br />

list-length r<strong>et</strong>urns the length of the list lisl. If list is circular. then list-length r<strong>et</strong>urns<br />

nil--in this it differs from length, which in r\lL will sign<strong>al</strong> an error but in other COMMON<br />

LISP implementations may fail to terminate.<br />

It is an error for Iisl to not tenninate with nil (assuming it is not circular). In this, listlength<br />

differs from its implementation in previous releases of <strong>NIL</strong>.<br />

copy-l1 s t list<br />

Copies the top-level cnnses of list. This may be used to replace the common idiom<br />

(append lis/ (»<br />

and. addition<strong>al</strong>ly. handles a non-null last cdr of lis/ gracefully.<br />

copy-<strong>al</strong>ist a-lisl<br />

Like copy-list. and addition<strong>al</strong>ly. each top-level clement of a-list which is a cons has that<br />

first cons copied <strong>al</strong>so (1101 tJle entire top-level of the a-list cntry).<br />

Note that this function name contains "<strong>al</strong>ist", a term which is spelled "a-list" everywhere<br />

else now.<br />

This replaces the LISP MACHINE LISP function copy<strong>al</strong>ist, which exists identic<strong>al</strong>ly in <strong>NIL</strong>.<br />

copy-tree tree<br />

R<strong>et</strong>urns a copy of tree. Recurses through both the car and the cdr. tcrminating at nonconses.<br />

That is. only conses are copied. This replaces the old MAC'l.lSP idiom<br />

(subst nil nil "eel<br />

which has been changed incompatibly by COMMON LISP (page 60).<br />

This function is thc COMMON I.ISP equiv<strong>al</strong>ent of the LISP<br />

function, which is defined in <strong>NIL</strong> as a synonym for copy-tree.<br />

MACHINE LISP copytree<br />

butlast list &option<strong>al</strong> (n/)<br />

This r<strong>et</strong>urns a copy of lisl, but without the last n elements. If the length of the list is<br />

less than or equ<strong>al</strong> to n, nil is r<strong>et</strong>urned.<br />

(butlast '(1 2 3» => (1 2)<br />

(butlast '(1 2 3) 2) => (1)<br />

(butlast '(I» => nil<br />

(but1ast nil) => nil<br />

nbut 1 ast list &option<strong>al</strong> (n I)<br />

Destructive version of butlast: the last n elements of list are "spliced out", by rplacd.<br />

nbutlast should be used for v<strong>al</strong>ue. however, because if the length of the list is less than<br />

or equ<strong>al</strong> to n, nil is r<strong>et</strong>urned and no "splicing" is perfonned.<br />

ta 11 P sublist list<br />

tailp r<strong>et</strong>urns t if sublist is a sublist of list. nil otherwise. What this means is that after<br />

taking some numbcr of cdrs of list (possibly l.cro), one gcts to a list eq to list.<br />

MC:<strong>NIL</strong>MAN:LIST 37


Substitution 60 <strong>NIL</strong> Manu<strong>al</strong><br />

1 d 1 ft list sublist<br />

If (taiJp sublisl list) is tnJe,ldiffC"1ist differencc") r<strong>et</strong>urns a list of the clements of lisl up<br />

to but not including sublist. This is the same as .<br />

( nbut 1 as t list (1 ength sublist})<br />

If (tailp sublist list) is f<strong>al</strong>se. Idiff simply r<strong>et</strong>urns a copy of list.<br />

8.2 Substitution<br />

These functions arc extensions of the subst and subJis functions which are defined by<br />

\1:\('1 ISP and liSP MAClIl~F IJSP. NOle LI),ll LIley by dcfhult usc eql to lest for equ<strong>al</strong>ity; Lllis is<br />

incompatible with MACI.1SJl mld an e,lrly release of Nil.. in which subst used equ<strong>al</strong> but sublis<br />

lIsed eq (but only worked on symbuls). A different tcst may be specified by usc of the :test<br />

keywordcd arg~lment: this is a predicate of two arguments used to test "cQu<strong>al</strong>ity". )f it is more<br />

convenient, the sense of the predicate may be reversed by usc of the :test-not keyword.<br />

Note <strong>al</strong>so thatthcse functions only descend through list structure ('·trees")~<br />

inside of vcctors. arrays. or other structures.<br />

they do not 100k<br />

subst new old tree &key test lest-not" key<br />

R cturnsa copy of tree. with n('w. substituted when a of the tree matches old according to<br />

the test.<br />

This is incompatible with MACUSP subst. in that the result is 1101 guaranteed to <strong>al</strong>ways<br />

copy even if substitution is not perfonned. TheMACUsp idiom (subst nil nil lrer) is<br />

replaced by the copy-tree function (page 59). Be on the lookout for the use of this<br />

idiom in old code. for it can cause obscure bugs when uncopied structure is modified.<br />

The Nil. compiler will warn about usc of this idiom and turn the subst into a ~1n to<br />

copy-tree if (1) there are no keyworded arguments supplied (2) Ilewand old arc constants<br />

d<strong>et</strong>erminable at compile-time and (3) their v<strong>al</strong>ues are eql. The runtime function cannot<br />

d<strong>et</strong>ect this idiom.<br />

nsubst new old tree &key lest lesl-.nol key<br />

Like subst •. but does not copy: the new components are destructively stored in tree.<br />

However, this should be used for v<strong>al</strong>uc, for if tree matches old.- the result is new but no<br />

bashing of list structure is done.<br />

sub 11 s ~list tree &kcy lest lest-llot key<br />

Like subst. but performs substitution for sever<strong>al</strong> things. at once. a-lisl is an association<br />

list of the· objects to match. and their replacements. For example,<br />

(sublis '«yes. no) (t . nil» '(t gener<strong>al</strong>ly means yes»<br />

=>(n11 gener<strong>al</strong>ly means no)<br />

sublis. remember, looks at cars and cdrs equiv<strong>al</strong>ently. If we attempt to invert the above<br />

example. we g<strong>et</strong><br />

(sublis '(no. yes) (nil. t» '(nil gener<strong>al</strong>ly means no»<br />

=> (t gener<strong>al</strong>ly means yes . t)<br />

MC:NI1.MAN:LIST 37<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 61 Using I ,ists as S<strong>et</strong>s<br />

nsub 11 s a-list tree &key test test-not key<br />

I.ike sublis. but destructive. See <strong>al</strong>so nsubst.<br />

8.3 Using Lists as S<strong>et</strong>s<br />

One common use of lists is as s<strong>et</strong>s of objects~<br />

of functions for doing this.<br />

<strong>NIL</strong> (and COMMON LISP) provide a complement<br />

All of the functions take similar arguments. Nonn<strong>al</strong>Iy. they use eql as their predicate. so that<br />

they work on numbers properly <strong>al</strong>so. If this is not suitable for the purpose. then a predicate may<br />

be specified by gh'ing it as the :test kcyworded argument. For instance.<br />

(union '«a b) (b) (e» '«d) (e) (a b) (b» :test "equ<strong>al</strong>)<br />

=> «a b) (b) (e) (d) (e})<br />

The scns~ of the predicate can be reversed by using :test-not instead of :test.<br />

Som<strong>et</strong>imes the c1ements of the s<strong>et</strong> arc d~lt41S1ructures of some sort. and one desires to only<br />

compare one part of the datastructure. but not write a predicate to compare things. If thc :key<br />

kcyworded argument is used. then that is a function which will be applied to each clement as it<br />

is tested. and the results of that will be given to the equ<strong>al</strong>ity predicate, rather than the elements<br />

themselves. for example,<br />

(union '«a) (b) (e» '«d) (e) (a) (b)) :key 'tcar}<br />

=> «a) (b) (c) (d) (e»<br />

The :key-specified function is only applied to elemenL~ extracted from lists, never to sin81~ ilpm<br />

arguments givcn to any of these functions (such as member. below). The ordering of the result<br />

may not be depended on; neither may the result if either of the inputs contains duplicate<br />

clements (as defined by the predicate). nor the particular choice of clement (that is. the one from<br />

the first list or the one from the second I~st). Thus.<br />

(union '«a) (b x) (c}) '«d) (e) (e) (b y» :key "car)<br />

might r<strong>et</strong>urn either of the s<strong>et</strong>s<br />

«a) (b x) (c) Cd) (e»<br />

or<br />

«a) (b y) (c) (d) (e»<br />

since they are equiv<strong>al</strong>ent according to the test criteria.<br />

member item list &key test test-not key<br />

If item is a member of list according to the specified test (which defaults to # 'eql). then<br />

member r<strong>et</strong>urns the sublist whose car satisfied the test. Otherwise. nil is r<strong>et</strong>urned. The<br />

other functions in this section (Ire implemented in terms of this. Note that if a function is<br />

specified with :key, it is only applied to items of list. not to item.<br />

Note that the default predicate for member. # 'eqJ. is incompatible with MACLISP member.<br />

This provides consistency with an other similar functions.<br />

memq item list<br />

This is member with a test of # 'eq. memq is not defined by COMMOl' USP, but is<br />

inherited from MACIJSP. It is speci<strong>al</strong>ly handled by the <strong>NIL</strong> compHer.<br />

MC:<strong>NIL</strong>MAN:I.IST 37<br />

23-DEC-83


• _ .,<br />

Using Lists (is S<strong>et</strong>s<br />

un ion lisll lis/2 &key<br />

s<strong>et</strong>-difference Ii.'ill lisl} ,&kcy lesl leSI-no/ key<br />

} are used to constructthc result.<br />

Rcturns the s<strong>et</strong> diffcrence of lisl! and lisl} (a list of the elcments of lisil which arc not<br />

present in lisl2. according to the predicate).<br />

ns<strong>et</strong>-difference list! lisI2 &'key leSI leSI-I1o/ key<br />

IJcstructi\,c s<strong>et</strong>-difference: the result is constructed from the conses of lisil and/or lisl!.<br />

s<strong>et</strong>-exclus ive-or lisll lis12 &key leSI lest-nol key<br />

R<strong>et</strong>urns a list of the clements which occur in eithcr lis" or lis/}. bill not both. according<br />

to the predicate.<br />

ns<strong>et</strong>-exclusive-or listl list2 &key leSI /esl-1101<br />

Destructive s<strong>et</strong>-exclusive-or: the result is constructed from the conses of lisil and/or.<br />

list2.<br />

subs<strong>et</strong>p Iisll lisl2 &key lesl IttSI-110/ key<br />

R<strong>et</strong>urns t if lisil is a SUbs<strong>et</strong> of (bUt not necessarily a proper subs<strong>et</strong> of) lisa. nil otherwise.<br />

adjoi n item lis/ &key leSI lesl-not key<br />

If ilem is a member of lisl according to the specified test, this just r<strong>et</strong>urns lisl: otherwise.<br />

it conscs ilem onto the front of list. and r<strong>et</strong>urns th<strong>al</strong> adjoin could have been defined as<br />

(defun adjoin (item list &rest keyworded-args<br />

&key test test-not key)<br />

(if (apply #'member item list keyworded-args)<br />

list<br />

(cons item list»)<br />

which <strong>al</strong>so shows the utility of the &rest keyword combined with &key.<br />

key<br />

MC:<strong>NIL</strong>MAN:I.IST 37<br />

23-DEC-S3<br />

-. . .<br />

. ..' . .:,..::,"'


<strong>NIL</strong> Manu<strong>al</strong> 63 Association I -ists<br />

8.4 Association Lists<br />

Association lists arc an abstraction built from lists which arc useful in many cases. An<br />

association lisl (or a-list, som<strong>et</strong>imes misspelled <strong>al</strong>isl in this document), is a list.. <strong>al</strong>l clements of<br />

which are conses: the car of each cons is the key, and the cdr of each cons is the data<br />

associated with that key. Association list~ differ slightly from just lists used as sequences utilizing<br />

a key of car (or cdr): if an entry in an association list is the atom nil, then it will be ignored<br />

tot<strong>al</strong>ly. Functions which de<strong>al</strong> with more gener<strong>al</strong> sequences or lists. such as member, find, and<br />

position. would blindly apply the supplied key (e.g.. car) to nil. and try matching this against<br />

the item being searched for.<br />

There are two common ways in which aSSOCiation lists are used. For one. what is being<br />

constructed is basic<strong>al</strong>ly just a lilb1e with entries of a single key. In this. the entries in the a-list<br />

are cnnses of the key and the data associated with the key. and one uses assoc with an<br />

appropriate test to do the lookup: the data of the key may be replaced by using rplacd on the<br />

result of the assoc. assuming assoc did not r<strong>et</strong>urn nil. There are two potenti<strong>al</strong> disadvantages<br />

with this approach. First, the lookup is linear. so the lookup time grows linearly with the length<br />

of the tahle. How much this matters depends on the efficiency of the equ<strong>al</strong>ity predicate in usc:<br />

eq is extremely fast. and eql is fairly fast, so this could matter a fair amount if they arc the<br />

predicates in usc. Second. because a-lists arc constnlcted out of C(lnses. they can be scattered <strong>al</strong>l<br />

over \'inu<strong>al</strong> memory and cause poor paging performance: it is possihle for each cons in an a-list<br />

to lie on a different page. If entries are only rarely added to or removed from the table (entire<br />

entries. not just update of the car or cdr of an a-list entry), it might be reasonable to ensure<br />

ta'iut th\: a liSi lk5 ira fairly cuntiguous virtud] Hi(;Jii\ii) b,)' \.:oJ.'yiug it wilil l;(JIJY-i2ii~i (page 59)<br />

when som<strong>et</strong>hing is added to it. Some rough guesses. with a test of eq: if the a-list has over 50.<br />

entries, it is probably b<strong>et</strong>ter to use a hash table. For 70 or 80. a hash table is vinu<strong>al</strong>1y<br />

guaranteed to be b<strong>et</strong>ter, unless most of the lookups wi1l succeed, and find entries near to the<br />

front. For b<strong>et</strong>ween 5 and 10 entries. an a-list is <strong>al</strong>most undoubtedly best. and can he optimized<br />

by copying with copy-<strong>al</strong>ist. For v<strong>al</strong>ues b<strong>et</strong>ween 10 and 50. the decision on which to use<br />

requires b<strong>al</strong>ancing additions and del<strong>et</strong>ions against wasting time (and creating garbage) using copy<strong>al</strong>ist.<br />

Probably it is best to only do the copying with copy-<strong>al</strong>ist for tables which are not updated<br />

in th,e "norm<strong>al</strong> course of program running", i.e., which might only be updated when new files are<br />

loaded.<br />

The other common use of a-lists is where the implicit ordering of a list comes into play. One<br />

entry in the association list might have the same key' as another which occurs "later" in the a-list;<br />

since association lists are <strong>al</strong>ways searched in left-to-right order, the first occurence will shadow any<br />

other occurences. A simple LISP lexic<strong>al</strong> interpr<strong>et</strong>er might use an association list to hold the lexic<strong>al</strong><br />

variable bindings, for instance. "Binding" pushes the new variable/v<strong>al</strong>ue pair on the front of the<br />

"environment" a-list. and "unbinding" pops the entry off. For this son of use, hash tables do<br />

not present an <strong>al</strong>ternative without some hairy hacking of "contexts".<br />

A third possible use of an a-list is for two-way associations; that is, the car and cdr may<br />

both be viewed as keys used to look. up the other: one uses assoc to find the entry by the car<br />

key, and rassoc to find the entry by the cdr key. Hash tables do not provide this son of<br />

service: if a-list lookup time is prohibitive in a particular case. the <strong>al</strong>ternative is to usc two hash<br />

tables.<br />

MC:NJI.MAN;I.IST 37<br />

23-DEC-83


Association l.ists 64 <strong>NIL</strong> Manu<strong>al</strong><br />

as soc item a-lisl &key lesl lesl-nol<br />

Searches a-lisl for an entry whose car matches ilem according to the specified test. I f one<br />

is found. that cons is r<strong>et</strong>urned; otherwise nil is r<strong>et</strong>urned. If a non-null result is r<strong>et</strong>urned,<br />

the datum of it may be modified by use of rplacd.<br />

Note <strong>al</strong>so that since the default test is # 'eql, this is incompatible with MACLISP assoc.<br />

To r<strong>et</strong>ain the same effect. one must· use<br />

(assoc item a-list :test "equ<strong>al</strong>)<br />

or simply assq (below). Of course. often the choice of assoc in MACTISP is because item<br />

is a number, so equ<strong>al</strong> is not needed in Nil becausc eql compares numhcrs correctly.<br />

ras soc il(,l11 a-/isl &key lesl lesl-l1ot key<br />

l.ike assoc, except that item is matched against each datum in a-lisl. rather than each<br />

key.<br />

assq item a-lisl<br />

This is inherited from MACl.lSP and <strong>al</strong>so .is defined by I.1SP MAClllt\F 1 JSP: it is 1101<br />

defined by CO\1~ON I.ISP. It is identic<strong>al</strong> to<br />

(assoc ilC111 a-Jisl : test #'eq)<br />

Compilation of assqdocs ·1101 produce any different code than the above fonn. so the<br />

choice b<strong>et</strong>ween the two is b<strong>et</strong>ween COMMON LISP compatibility and verbosity in the source<br />

code.<br />

r"~~q<br />

i'I'''' n-If~!<br />

'111is is inherited from LISP MACHINE LISP; it is not defined by COMMOT' LISP.<br />

same as<br />

(rassoc item a-list :test I'eq)<br />

Sec assq (above) for more qu<strong>al</strong>ifications.<br />

It is the<br />

aeons key datum a-liSI<br />

This is the same as<br />

{cons (cons key datum) a-lis/)<br />

but shows the intent b<strong>et</strong>ter.<br />

pa 1 rl1 s keys data &option<strong>al</strong> a-Iist<br />

R<strong>et</strong>urns an a-list made by associating keys and d<strong>al</strong>a and adding them to the front of a-iisl<br />

(which defaults to nil). keys and data must be lists of the same length.<br />

(pairlis '(foo bar) '("Foo" "Bar") '«baz . "Baz"»)<br />

=> ( (foo . "Foo") (bar . "Bar") (baz . "8az"»<br />

The result will share structure with a-list (that is. (tailp a-list paiTIi~result) is 0, so<br />

modifications to the associations in the r<strong>et</strong>urned result will atfectthose assocations in a-list<br />

<strong>al</strong>so.<br />

MC:NII.MAN;I.IST 37<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 65 Symbols<br />

9. Synlbols<br />

9.1 The Property List<br />

See <strong>al</strong>so section 5.10, page 39, which de<strong>al</strong>s with property lists in a more gener<strong>al</strong> way.<br />

symbo 1 - P 11 s t symbol<br />

R<strong>et</strong>urns the property list of symbol. Unlike the MACLISP pUst function. this only works<br />

on symbols. not disembodied property lists.<br />

symbol- pHst J11~ly he used with s<strong>et</strong>f to change the property list of a symhoL This is<br />

gener<strong>al</strong>ly not rec()mmcnd~dpraclicc. however. because doing so might c<strong>al</strong>lsc properties<br />

essenti<strong>al</strong> to tllC ~Jl. system to be lost.<br />

g<strong>et</strong> sJ'Il1bul indicator<br />

Standard MAC'I.ISI) ·g<strong>et</strong>. The v<strong>al</strong>ue stored under indica/or on the property list of symbol is<br />

r<strong>et</strong>urned: if tllere is no such v<strong>al</strong>ue. nil is r<strong>et</strong>urned. As in MACUSP. symbol may <strong>al</strong>so be a<br />

disemhodied property list. Unlike in MAC'I.lSP. g<strong>et</strong> docs not arhirrarily check the type and<br />

then r<strong>et</strong>urn nil if it is ncitller a symbol nor a list; in :-';11. one g<strong>et</strong>s an error for an inv<strong>al</strong>id<br />

type.<br />

For both MACLISP compatibility and convenience. g<strong>et</strong> is not going to disappear in tlle<br />

future.<br />

putprop s),mbol v<strong>al</strong>ue indicator<br />

Standard MACLISP putprop. If symbol <strong>al</strong>ready has an indica/or property. tllis replaces it<br />

with v<strong>al</strong>ue. otherwise puts a new one. As in MACLlSP, symbol may <strong>al</strong>so be a disembodied<br />

property list<br />

COMMO~ LISP does not define putprop: rather. one uses s<strong>et</strong>f with g<strong>et</strong>f (page 39).<br />

putprop is not going to be flushed from <strong>NIL</strong>, however. Note <strong>al</strong>so that putprop takes its<br />

arguments in a different order from the "standard s<strong>et</strong>f order" in which the v<strong>al</strong>ue being<br />

s.tored comes last<br />

remprop symbol indicator<br />

Standard MACUSP remprop. If symbol has an indica/or propcrty, then that is removed by<br />

being spliced out of the property Jist. and tlle subHst of tllc property list whose car is the<br />

v<strong>al</strong>ue (being removed) is r<strong>et</strong>urned. If there is no such property, nil is r<strong>et</strong>urned. For<br />

instance, if one does<br />

(putprop 'kitty 'yu~shiang 'flavor)<br />

then<br />

(remprop 'kitty 'flavor)<br />

= > ( y u - s h ian 9 and maybe some subllsl 0/ the property list)<br />

. See <strong>al</strong>so the remf macro, page 40 .. for removing properties from property lists stored in<br />

arbitrary places.<br />

MC:<strong>NIL</strong>MAN;SYMBOL 30<br />

23-DEC-83<br />

'.<br />

'<br />

; ~ ---- . ~ ~<br />

. - ~ ~ - .<br />

, ". ,', ~~< .'. . ~ '. "-,'.::,'" .. " ,- - . ~, . ' "'". ..." ..".. '. .. "",', .; "


The Prill( Name<br />

66<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

Note: COMMON USP docs not define the actu<strong>al</strong> v<strong>al</strong>ue r<strong>et</strong>urned by remprop. only that it<br />

will be null if the property was not found, non-null if it was. The v<strong>al</strong>ue r<strong>et</strong>urned by <strong>NIL</strong><br />

remprop is compatible with MACLISP. and wilJ be r<strong>et</strong>ained fi)r that compatibility.<br />

9.2 The Print Name<br />

symbol-name symbol<br />

R<strong>et</strong>urns the name of symbol. which is a string.<br />

Note that a string which is a symbol name should never be modified: ncitJler should the<br />

name of a symbol be changed.<br />

In ~II .•<br />

the name Of.'l symbol will <strong>al</strong>ways be a simple string.<br />

The mime of a symhol has variously been c<strong>al</strong>Jed a prilll 1Iame and a pname. tenns which<br />

are being phased out but· stiU pervade the <strong>NIL</strong> implementation.<br />

samepnamep s)'1171<br />

sym2<br />

R<strong>et</strong>urns t if syml and sym2 have equ<strong>al</strong> print names. Case is significant. syml and s)'1112<br />

may be strings too. Either (or both) of the symbols may be specified as strings instead~<br />

samepnamep is reany just a MACLISP function. It is obsol<strong>et</strong>ed by string = (page 113).<br />

because the string comparison functions in SIL will accept symbols and perfonn the<br />

comparison on their namcs.<br />

9.3 Creating Symbols<br />

make-symbol pname<br />

Makes a new uninterned symbol whose print-name is the string pname. It will have no<br />

v<strong>al</strong>ue or function bindings. no package, and an empty propeny list<br />

That the print-name (as r<strong>et</strong>urned by symbol-print-name) of the r<strong>et</strong>urned symbol will be<br />

eq to p"ame should not be depended upon.<br />

copy-symbol sym &option<strong>al</strong> coprprops<br />

If copy-props is nil. then this is the same as (make-symbol (symbol-name S)'111»; that is<br />

t<br />

it r<strong>et</strong>urns a virgin symbol with the same print-name as sym. If Coprprops is not nil then<br />

t<br />

the v<strong>al</strong>ue and function definition and propeny-Jist and package of sym wiJI be copied to<br />

the new symbol.<br />

Actu<strong>al</strong>ly. the current dynamic bindings (v<strong>al</strong>ue and function) of sym are copied to the new<br />

glob<strong>al</strong> dynamic bindings of the new symbol.<br />

,<br />

copy-symbol with a nun copy-props argument is a reasonable way to generate a unique<br />

symhol which is somewhat mnemonic <strong>al</strong>though not compl<strong>et</strong>cJy visu<strong>al</strong>ly unique. The <strong>NIL</strong><br />

compiler copics symbols like if-f<strong>al</strong>se to generate tags. for instance: no new print name is<br />

created. just the basic symbol structure. on which· properties can be placed. If the symbol<br />

is to be used as a variable in macro expansions, however. it may be b<strong>et</strong>ter to use<br />

MC: N I LM 1\ N :SYM BOL 30<br />

23-DEC-83<br />

. . - . -<br />

, -' . .. . . . - - .' - '<br />

> .>.>, .. ". >' ••.. " .. "J'~>: .; .• 'i}/:'~ "1:'...,',,) >":, ~";>"


<strong>NIL</strong> Manu<strong>al</strong> 67 Creating Symhols<br />

gentemp (below).<br />

gensym &option<strong>al</strong> x<br />

Standard inherited-from-MACLISP gensym. gensym creates new uninterned symbols. The<br />

print name of the symbol is constructed by prepending a single character prefix' to the<br />

decim<strong>al</strong> representation of a counter which g<strong>et</strong>s incremented every time gensym is c<strong>al</strong>led.<br />

The name has been around for so long that automatic<strong>al</strong>1y generated names arc commonly<br />

refered to as geIlSYI1lS, and the act of doing so as gl'flsyming.<br />

(gensym) r<strong>et</strong>urns such a constructed symbol.<br />

(gensym lI<strong>al</strong>ll£» s<strong>et</strong>s the prefix to he n<strong>al</strong>ll£>. which must be a string or a svmhol. and<br />

then makes a gensym. (In ~1AC1.lSP. only the first character of name is used: in NIl.. the<br />

entire name is.)<br />

(gensym illteger) s<strong>et</strong>s the counter to i11leger, and then makes a gensym. illIeger must<br />

not be negative.<br />

gentemp &option<strong>al</strong> prefix package<br />

gensym creates a symbol in a manner similar to gensym. but interns it in package<br />

(which defaults to the current package). Addition<strong>al</strong>ly, gentemp guarantees that the<br />

symbol is unique by continuing to increment its intern<strong>al</strong> counter until it succeeds in<br />

constructing a symbol which has nol <strong>al</strong>ready been interned in package.<br />

Unlike gensym. the prefix argument to gentemp is not "sticky": that is. it does not<br />

default to the last one supplied. If it is not supplied, it defaults to t. Also, there is no<br />

provision for res<strong>et</strong>ting the intern<strong>al</strong> counter.<br />

Use this for creating variables for usc in macro expansions. because the symbol can be<br />

typed in .. Also, gentemp will leave some infonnation around so that code an<strong>al</strong>yzers or<br />

the compiler can see that the variable is a generated variable so may . be optimized away<br />

without loss of debugging infonnation. (Nonn<strong>al</strong>1y such a test would be that the symbol is<br />

not interned. i.e .. it was created by gensym or copy-symbol. lbis does not work for<br />

gentemp because gentemp interns the symbol so it can be typed in for debugging.) In<br />

1'11... gentemp-crcatcd symbols are flagged by having a non-null si:gentemp-marker<br />

property.<br />

symbol-package symbol<br />

This r<strong>et</strong>urns the "home package" of symbol, or nil if symbol does not have one (it is not<br />

interned).<br />

MC:<strong>NIL</strong>MAN:SYMBOL 30<br />

23-DEC-83<br />

. .... ...• ~ ,.


a<br />

The V<strong>al</strong>ue and FunctiunCeHs 68 Nil. Manu<strong>al</strong><br />

9.4 The V<strong>al</strong>ue and Function Cells<br />

See <strong>al</strong>so chapter 3. page 11 k)r discussion about scope. extent. and binding. and chapter 3.<br />

page 11 for a description of the <strong>NIL</strong> intern<strong>al</strong> mechanism for performing variable and function<br />

binding.<br />

Speci<strong>al</strong> implementation qu<strong>al</strong>ification: because of the hairy v<strong>al</strong>ue cell mechanism in <strong>NIL</strong>. v<strong>al</strong>ue<br />

cells arc not just <strong>al</strong>located in the heap. so (due to lack of code to do some relocation right now)<br />

there is an assembly-timc timi~ltjon on how many may he cremed. Thus, generating symbols and<br />

using the v<strong>al</strong>uc cells to store things may not work as . well as you expected (an error complaining<br />

NEW_SLINK wants to grow the SLINK occurs). This limil4ltioll is nol a function of the<br />

mechanism but rather of the Im:k of garb.lge-collccior. however.<br />

symbo l-V8 1 ue symbol<br />

R<strong>et</strong>urns the current dynamic (speci<strong>al</strong>) vaJucof symbol.<br />

symbol-v<strong>al</strong>ue may be used with s<strong>et</strong>f.<br />

boundp symbol<br />

R<strong>et</strong>urns t if symbol has a defined dynamic (speci<strong>al</strong>) v<strong>al</strong>ue, nil otherwise. Note that<br />

(s<strong>et</strong>q *foo* 1) => 1<br />

(l<strong>et</strong> «.foo. 3»<br />

(declare (speci<strong>al</strong> .foo.»<br />

(makunbound '.foo*)<br />

(boundp '*foo*»<br />

=> nil<br />

=> 1<br />

makunbound symbol<br />

"Undefines" the current dynamic v<strong>al</strong>ue of symbol.<br />

An error is sign<strong>al</strong>led if symbol is a constant (as defined by defconstant).<br />

symbol-function symbol<br />

R<strong>et</strong>urns the current dynamic (speci<strong>al</strong>) function v<strong>al</strong>ue of symbol. The result of symbolfunction<br />

on a symbol defined as a macro or speci<strong>al</strong> fonn is undefined in COMMON LISP.<br />

In <strong>NIL</strong>. speci<strong>al</strong> fonn definitions are not stored here, but other kinds of function<br />

definitions are.<br />

symbol-function may be used with s<strong>et</strong>f.<br />

fboundp symbol<br />

R<strong>et</strong>urns t if symbol has a defined dynamic function v<strong>al</strong>ue, nil otherwise. (Like boundp.)<br />

fmakunbound symbol<br />

An<strong>al</strong>ogous to· makunbound.<br />

MC:<strong>NIL</strong>MAN;SYMBOL 30<br />

23-DEC-83


••<br />

Nil. Manu<strong>al</strong> 69 Addition<strong>al</strong> Names<br />

9.5 Addition<strong>al</strong> Names<br />

Some other MACLlSP-compatibJe. LISP MACJlJI':E LIsP-compatible, and older <strong>NIL</strong>-compatible<br />

names.<br />

symev<strong>al</strong> symbol<br />

Same as symbol-v<strong>al</strong>ue, page 68.<br />

s<strong>et</strong> symbol v<strong>al</strong>ue .<br />

Same as (s<strong>et</strong>f (symbol-v<strong>al</strong>ue symbol) v<strong>al</strong>ue).<br />

fsymev<strong>al</strong> symbol<br />

Same as symbol-function. page 68.<br />

fs<strong>et</strong> ,symbol fUllc/ion<br />

Same as (s<strong>et</strong>f (symbol-function symbol) function).<br />

~ u t - P name symbol<br />

Same as symbol-name. page 66.<br />

P 11 st symbol<br />

Same as symbol-pJist. page 65. Note that this is not exactly the same as the MACLISP<br />

plist function (maybe it should be made to be?). The MACUSP plist function "works" on<br />

disembodied property lists (specific<strong>al</strong>ly. it takes the cdr of a list) - this is sort of an<br />

artifact of the MACLISP implementation.<br />

s<strong>et</strong>p 11 st symbol new-plisl<br />

The same as (s<strong>et</strong>f (symbol-plist· symbol) new-pUst).<br />

qu<strong>al</strong>ifications hold as for plist.<br />

The same MACLlSP-compatibility<br />

g<strong>et</strong> 1 symbol indicator-list<br />

Standard MACLISP g<strong>et</strong>f. R<strong>et</strong>urns the subpart of the property list of symbol beginning with<br />

the first indicator found in the list indicator-Ust, or nil if none was found. As in<br />

MACLlSP, symbol may <strong>al</strong>so be a disembodied property list. Essenti<strong>al</strong>ly, this is the third<br />

v<strong>al</strong>ue r<strong>et</strong>urned by<br />

(g<strong>et</strong>-properties<br />

(if (symbolp symbol) (symbol-plist symbol) (cdr symbol»<br />

indicator-list)<br />

copysymbol symbol &option<strong>al</strong> copy-props<br />

MACLISP name for copy-symbol (page 66). Note that in MACUSP, however, copy-props<br />

is a required argument.<br />

~1C:<strong>NIL</strong>MAN:SYMROL 30<br />

23-DEC-83


Symbol COllc<strong>al</strong>cnt<strong>al</strong>ion<br />

9.6 Symbol Concatentation<br />

70<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

'Ibc following routines are not defined· by COMMON IJSP. but arc fairly useful in lIteir own<br />

right by macros <strong>et</strong>c.<br />

symbo 1 conc &rest frobs<br />

symbolconc r<strong>et</strong>urns a new symbol (interned in lite current package) whose name is lite<br />

concatenation of lite names of frobs. Typic<strong>al</strong>ly. each frob is a symbol. however<br />

symbolconc <strong>al</strong>so <strong>al</strong>lows it to be a fixnum (in which case its dccim.1I printed<br />

represcntation is usro). a sIring. or a character (which must be convertihle 10 a string.<br />

i.c .. satisty string-char-p).<br />

sf: package- symbo 1 conc /'f.J('kagr-sp('C' &rcs( frobs<br />

Simii


--<br />

._-_.-..<br />

-_._----------------------<br />

N II. Manu<strong>al</strong> 71 Numbers<br />

10. Numbers<br />

10.1 Types" Contagion, Coercion, and Confusion<br />

10.1.1 The Types<br />

Nn. provides sever<strong>al</strong> different representations for numbers. It provides integers. of essenti<strong>al</strong>ly<br />

unlimited precision. and floating-point. There is <strong>al</strong>so the ratio data type. for representing noninteger<br />

ration<strong>al</strong> numhers. The complex daw type has heen added. but may not y<strong>et</strong> be<br />

trustworthy for anything other than simple arithm<strong>et</strong>ic operations. and has not y<strong>et</strong> been speci<strong>al</strong>ized<br />

to a point where any significant "crunch" might be performed on it.<br />

<strong>NIL</strong> integers arc currently of two kinds. There arc jixllulIlS and bignulIls . . Fixl1ums have 30<br />

hits of precision. inc1uding the sign. and arc represented without cnnsing (i.e.. no memory<br />

consumption). Integers which reqL'ire more ~an 30 bits to represent are implemented as bignums.<br />

lJigllUII1S arc an extended data-type. and can grow to any size, limited only by whate\er system<br />

param<strong>et</strong>er happens to be limiting the growth of your NIl .• and your patience.<br />

There arc four primitive floating-point fonnats supported in <strong>NIL</strong>, as described in section 2.1,<br />

page 3. These are<br />

short-float<br />

This is implemented as a single-float (VAX f _ f loa t format) with some of the fraction<br />

bits tnmcated. so that it can fit into a !\IL pointer without any memory consumption. An<br />

operations on this type essenti<strong>al</strong>ly convert it to a single-float to perform the operation. and<br />

then pack it back (truncating some of the fraction bits) when it is r<strong>et</strong>urned. 5 of the<br />

fraction bil~ g<strong>et</strong> truncated. leaving 19. or about 5 decim<strong>al</strong> digits of precision. Because the<br />

exponent is the same as for single-float. it has close to the same range. however.<br />

single-float<br />

This corresponds to the VAX f _ float format; this provides 24 bits of precision (about 7<br />

decim<strong>al</strong> digits), and a range of about 2.ge-39 to l.7e+ 38.<br />

double - float<br />

This utilizes the VAX d_float format. which has 56 bits of precision (about 16 decim<strong>al</strong><br />

digits). The exponent fonnat is identic<strong>al</strong> to that of single-float, so the range _ is<br />

essenti<strong>al</strong>ly the same.<br />

long-float<br />

This utilizes the VAX h_float fonnat. This has a whopping 113 bits of precision (33<br />

decim<strong>al</strong> digits), and binary exponent range from -16383 to + 16383. This is a range of<br />

about 8.4e-4933 to 5.ge+4931. Because the machine instructions which operate on this<br />

format of float are not supponed by <strong>al</strong>l VAX hardware. <strong>NIL</strong> makes use of a VMs-supplied<br />

condition handler to cause emulation of the missing instructions. As a compromise. it <strong>al</strong>so<br />

tries to avoid such instructions when it can (for instance, just for data movement).<br />

MC:<strong>NIL</strong>MAN:NUMBER 70<br />

23-DEC-83


Types. Contagion. Coercion, and Confusion 72 <strong>NIL</strong> Manu<strong>al</strong><br />

10.1.2 Contagion and Coercion<br />

Most of the <strong>NIL</strong> arithm<strong>et</strong>ic functions are gelleric. rlbat is.. they accept numbers of any type<br />

(subject to the semantics of the functiun. of course). and automatic<strong>al</strong>ly "coerce" as necessary<br />

when there are mixed types. Coercion is mainly a function of the floating-point types. For<br />

instance. division of integcrs might yie1d a ratio:<br />

(I 2 3) => 2/3<br />

Howcver. ration<strong>al</strong> numbcrs are <strong>al</strong>ways ·'norm<strong>al</strong>izcd". and automatic<strong>al</strong>ly "convert" back to intcgers:<br />

(+ 1/3 2/3) => 1<br />

When a flo,ning-point numher mcct~ an integer or a floating~ptlint numbcr uf a "shorter" type.<br />

the latter is cOIn crtcd autumatic<strong>al</strong>ly to thc format of thc .ftlftTIer bcfore thc operation procccds:<br />

(. 2 2.0s0) => ~.OsD<br />

(. 2 2.0dO 2.050) => 8.0dO<br />

Such coinagiolls convcrsion is ncvcr performed in the othcr direction: floating point numbcrs arc<br />

ne\cr COll\'crtcd to integers just because the rcsult might bc intcgr<strong>al</strong>. for cxamplc. or ttl a shortcr<br />

forr< at of float.<br />

Complex numbers in Nil. are restricted to having components which are either both ration<strong>al</strong>.<br />

or both floats of the same format. A complex number with ration<strong>al</strong> components will automatic<strong>al</strong>ly<br />

be converted back to a ration<strong>al</strong> (non-complex) number if the result of a computation gives a zero<br />

imaginary part. This never occurs if the components are· floats:<br />

(. Nc(O 1) Nc(O I)} => -1<br />

(. Nc(O.O 1.0) Nc(O.O 1.0» => Nc(-I.O 0.0)<br />

J 0.1.3 Confusion<br />

As was described in section 2.1. page 3. the fonnat of a floating-point number may be<br />

selected by use of a particular character as the exponent specifier. 'Ibus; 2.0s0 is short-float,<br />

2.0fO is single-float. 2.OdO is double-float, and 2.010 is long-float. COMMON uSPspecifies<br />

that the default fonnat is Single-float. 'Ibis is the fonnat which is used when a floating-point<br />

number is read in. and either no exponent character is used, or one of e is used (e.g., 2.5gel 0).<br />

This is <strong>al</strong>so the format specified as being r<strong>et</strong>urned by exponenti<strong>al</strong>. transcendent<strong>al</strong>, or irration<strong>al</strong><br />

functions when given ration<strong>al</strong> inputs. <strong>NIL</strong> has historic<strong>al</strong>ly had a default (in fact, it used to be the<br />

only) format of double-float. Becausc single-float (and shon and long) are <strong>al</strong>l quite new to <strong>NIL</strong>,<br />

the default format is still double -float. That is. currently<br />

(typep 2.59 'double-float) => t<br />

(typep (log 3/4) 'double-float) -> t<br />

However. Ihis will be changed. The <strong>NIL</strong> reader/printer combination has been twiddlcd somewhat<br />

so that while the default fonnat chosen by read is double-float, the printer will <strong>al</strong>ways print<br />

the exponent character which will force the fonnaL<br />

*read-default-tloat-tormat-<br />

Variable<br />

This variable (which is defined by COMMON USP) names the type of float which read<br />

should create when it encounters one which does not specify the format. It should have<br />

as its v<strong>al</strong>ue short-float. single-float. double-float. or long-float. The COMMON LISP<br />

default for this. is single-float.<br />

MC:NII.MAN;NUMBER 70<br />

23-DEC-83


a<br />

. .<br />

.... .. , ~(::ll;'~.:~j;i~~:~ ... ·3iL,·~L·;:~~iti~:';' .<br />

<strong>NIL</strong> Manu<strong>al</strong> 73 Predicates on Numbers<br />

As a speci<strong>al</strong> interim hack. !'Il. <strong>al</strong>lows this variable to have nil as its v<strong>al</strong>ue. This is taken<br />

to mean (to the reader) to produce double-float by default. but (to the printer) to not<br />

usc an "unspecified" fonnat on output. That is. with .read-default-float-format* being<br />

nil. the prir~ter will never produce "1.0", but rather "1.OdO".<br />

It is strongly recommended that explicit usc ()f coercion (using the float function, page 78) be<br />

made wherever the type of the result might matter. when using functions which must convcrt into<br />

floating-point befi)rc procceding. This includes things like log sin. and sqrt. Note <strong>al</strong>so that<br />

certain operations on complex numhers with ration<strong>al</strong> components. such as abs. implicitly usc<br />

these other functions: for instancc.<br />

(abs #c(3 4)) => 5.0dO<br />

10.2 Predicates on Nunlbers<br />

Note <strong>al</strong>so the type predicates numberp. bignump. integerp. fixnump. floatp. ratiop.<br />

ration<strong>al</strong>p. and complexp.<br />

zerop number<br />

R<strong>et</strong>urns t if number is intcger, floating-point. or complcx lero. nil otherwise.<br />

P 1 usp nOll-complex-number<br />

m1 nusp non-complex-number<br />

R<strong>et</strong>urn t if non-complex-number is of the appropriate sign. nil otherwise.<br />

oddp integer<br />

evenp integer<br />

R<strong>et</strong>urn t if integer is odd (even), nil otherwise.<br />

In <strong>NIL</strong> (but 1101 COMMON USP), oddp and evenp have been extended to gaussian integers.<br />

evenp is defined as divisibility by 1 + i. and oddp as being not evenp. This definition<br />

has the propeny that exactly h<strong>al</strong>f of the gaussian integers are odd and h<strong>al</strong>f are even.<br />

While there is a remote possibility that this definition will be changed, I consider it very<br />

unlikely.<br />

10.3 Comparisons on Numbers<br />

• number &rest more-numbers<br />

/- number &rest more-numbers<br />

< number &rest more-numbers<br />

> number &rest more-numbe1'$<br />

- number &rest more-numbers<br />

Thcse functions each take one or more arguments. If the scqucnce of arguments satisfies<br />

a cenain condition:<br />

MC:<strong>NIL</strong>MAN:NUMBER 70<br />

23-DEC-83


Arithm<strong>et</strong>ic Operiltions 74 <strong>NIL</strong> Manu<strong>al</strong><br />

= an the same<br />

I = aU different<br />

< monotonic<strong>al</strong>ly increasing<br />

> monotonic<strong>al</strong>ly decreasing<br />

= monotonicaJIy nonincreasing<br />

then the predicate is· true, and otherwise is f<strong>al</strong>se.<br />

Complex numhers arc only acceptable as arguments to = and / =: the others require<br />

their arguments to be non-complex.<br />

These functions <strong>al</strong>so h4t\"e fixJlum-only and duuble-fioat-only versions.<br />

greaterp 1111111/<br />

I1UlII} & rest more-lJumbers<br />

.1 as s p IIUfIiI ,lIum2 &rest more-l1umbers<br />

These are implemented as synonyms of < and >. and exist for MACI.ISP compatibility.<br />

ma.': number &rest more-llumbers<br />

m1 a I1l1l11be,. &rest morc-numbers<br />

Generic max/min. Works on any non-complex numbers. Note <strong>al</strong>so the existence of<br />

max& and min& (page 87), which only work on fixnums, and max$ and min$ (page 91),<br />

which only work ondouble-ftoats.<br />

10.4 Arithm<strong>et</strong>ic Operations<br />

+ & rest numbers<br />

plus & rest numbers<br />

R<strong>et</strong>urns the sum of <strong>al</strong>l of the numbers. pcrfilrming type coercion as appropriate. If there<br />

are no numbers. 0 is r<strong>et</strong>urned. The name plus is r<strong>et</strong>ained for MACLlSP compatibility.<br />

Note <strong>al</strong>so the fixnum-only + &, and double-float-only + $.<br />

1+<br />

addl number<br />

( P 1 us number 1)<br />

The nameaddl is r<strong>et</strong>ained primarily for MACLISP compatibility.<br />

- number &rcst numbers<br />

With one argument. - r<strong>et</strong>urns the negative of that argument. With more than one<br />

argumcn~ it subtracts <strong>al</strong>l of the others from the first. Type coercion is performed as<br />

necessary. Note <strong>al</strong>so the fixnum-only -a. and double-float-only -$ functions.<br />

d1 fference number &rest numbers<br />

When given more than one argument. difference subtracts from the first argument <strong>al</strong>l the<br />

others. and r<strong>et</strong>urns lhe result \Vhen given one argument. difference r<strong>et</strong>urns it. This is<br />

noteworthy because it is compatible with the MACLISP difference function. and it is<br />

illcompatible with - above.<br />

MC:<strong>NIL</strong>MAN:NUMBER 70<br />

23-DEC-83


»<br />

Nil, Manu<strong>al</strong><br />

75<br />

Arithmctic Operations<br />

1- llumber<br />

sub 1 number<br />

(- number 1)<br />

'Inc name sub1 is r<strong>et</strong>ained for MACLISP compatibility.<br />

m1 nus number<br />

This is the same as (- number): the name is r<strong>et</strong>ained for MACI.ISP compatibility.<br />

• & rest numbers<br />

t 1mes &rest numbers<br />

Rcturns the product of <strong>al</strong>l of the numbcrs. coercing as appropriate. The identity filr this<br />

opcr,ltion is 1. The name times is r<strong>et</strong>aincd ftlr \1Al'I.ISP compatibility.<br />

I I11lIl1ber &rest numbers<br />

This is the generic ration<strong>al</strong>izing division function. With one argument. / reciprocates the<br />

argument: with more than one. it divides the first by <strong>al</strong>l the others. and r<strong>et</strong>urns the<br />

resull. / will r<strong>et</strong>urn a ratio if the mathe1T!:\tic<strong>al</strong> quotient of two integers is not an eX:lct<br />

integer: truncming integer division is pel f(lnned by the ~1AC'l.lSP compatible quotient<br />

function. and variolls sorts of truncation and rounding (not limitcd to fio,lting-point<br />

input"') arc provided by the floor. ceiling. truncate. and round functions (section 10.7,<br />

page 79).<br />

quot 1 ent number &rest more-numbers<br />

Tn'" i" th(' MA.C'f ISP-('('mpatib!r quotient fun~tion. Wh~n g!ven more th.;!n ~~ne ~rgmnent.<br />

quotient divides the first hy <strong>al</strong>l the others. and r<strong>et</strong>urns the result. With one argument,<br />

r<strong>et</strong>urns that argument.<br />

If quotient is given integer arguments. it perfonns truncating division (see truncate. page<br />

79). However, if any of the arguments are ratios. it will instead do ration<strong>al</strong> division, like<br />

I.<br />

conjugate number<br />

R<strong>et</strong>urns the complex conjugate of number, which is number itself if number is not<br />

complex.<br />

gcd &rest integers<br />

R<strong>et</strong>urns the greatest common divisor of the integers. With no arguments. ged r<strong>et</strong>urns O.<br />

In <strong>NIL</strong>. ged works on <strong>al</strong>l gaussian integers. The result will <strong>al</strong>ways lie within the first<br />

quadrant, or <strong>al</strong>ong the positive re<strong>al</strong> axis.<br />

1 cm integer &rcst more-integers<br />

R<strong>et</strong>urns the least common multiple of the integers.<br />

Like gcd. lem in <strong>NIL</strong> works on <strong>al</strong>l gaussian integers.<br />

MC:NII.MAN:NUMBER 70<br />

23-DEC-83<br />

~:.


I rration<strong>al</strong> and Transcendent<strong>al</strong> Functions 76 NII~ Manu<strong>al</strong><br />

10.5 Irration,l1 and Transcendent<strong>al</strong> Functions<br />

Remember that the functions in this scction which must perfbnn their operations in floating ..<br />

point. will convert ration<strong>al</strong> numbers to double-float currently. but to single-float in the future.<br />

pi<br />

Const<strong>al</strong>lt<br />

The v<strong>al</strong>ue of this constant is pi. in the. longest floating-point fonnat available; in NJ~ this<br />

is a long-float. To use a shoner fonnat of pl. for instance double-float. one should use<br />

som<strong>et</strong>hing like one of the fonns<br />

(+ (float pi O.OdO) n)<br />

( + (c 0 ere e pi' do u b 1 e-flo at) II}<br />

to an)id hm'jng the v<strong>al</strong>ue of pi cause coercion to 'long-float in your cumputatiuns. Uses<br />

of both coerce and float like the above will be optimized by the compilerc into the<br />

appropriilte v<strong>al</strong>ue.<br />

I f other similar constants arc added to <strong>NIL</strong>. thcy <strong>al</strong>so will be in 10ng-fl()~1t<br />

should be treated similarly.<br />

fimnat. and<br />

10.5.1 Exponenti<strong>al</strong> and Logarithmic Functions<br />

8XP number<br />

R<strong>et</strong>urns e raised to the power number. where e is the base of the natur<strong>al</strong> logarithms. If<br />

lIumber is a float. the answer is computed and r<strong>et</strong>urned in the same fonnat: if it is<br />

ration<strong>al</strong>. it is first convcrtcd to double-float.<br />

exp t base-number power-number<br />

R<strong>et</strong>urns base-number raised to the power power-Ilumber. If base-number is a ration<strong>al</strong><br />

numher and the power-number is an integer. the c<strong>al</strong>culation will be exact and the result<br />

will be a ration<strong>al</strong> number. Otherwise. the c<strong>al</strong>culation devolves into fioating-point. and will<br />

use a logarithmic computation if power-number is not an integer.<br />

log number &option<strong>al</strong> base<br />

R<strong>et</strong>urns the logarithm of number in the base base. which defaults to e, the base of the<br />

natur<strong>al</strong> logarithms. lbe rules of contagious coercion apply here: number and base are<br />

converted to the largest format of the two, unless both are ration<strong>al</strong>. in which case they<br />

are converted to double-float.<br />

It is an error if number is zero, unless base is zero. in which case the log is taken to be<br />

zero.<br />

sqrt number<br />

R<strong>et</strong>urns the principaJ square root of number. If number is ration<strong>al</strong>, it is converted to a<br />

double-float first; sqrt in <strong>NIL</strong> never produces a ration<strong>al</strong> number even if number might<br />

have a ration<strong>al</strong> square root. even though this is not dis<strong>al</strong>lowed by COMMON USP.<br />

If number is a negative non-'complcx number. a complex number is r<strong>et</strong>urned.<br />

MC:NII.MAN;NUMBER 70<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 77 Irration<strong>al</strong> and Transcendent<strong>al</strong> Functions<br />

1sqrt integer<br />

Integer square-root: the argumentmllst be a non-negative integer. and t11e result is the<br />

greatest integer less than or equ<strong>al</strong> to the exact positive square root of the argument.<br />

10.5.2 Trigonom<strong>et</strong>ric and Related Functions<br />

abs number<br />

R<strong>et</strong>urns the absolute v<strong>al</strong>ue of the argul!1ent. which may be any type of number.<br />

When applied to the complex plane. abs r<strong>et</strong>urns the disL4mce of t11e point from the<br />

origin. which is<br />

(sqrt (+ (expt rea/pari 2) (expt imagpart 2»).<br />

Thus. for complex numbers. the result will <strong>al</strong>ways he floating-point hecause t11ere is a<br />

$qrt hidden away in the computation. Applications which require only cOll1paring<br />

distances from the origin may use t11e aho,"e f(lrm without the sqrt operation~ this is<br />

done. for instance. hy the intern<strong>al</strong> code for ged of complex integers.<br />

s 1 9 n um number<br />

By definition.<br />

(signum x) - (if (zerop x) x (I x (abs x»)<br />

signum of an ration<strong>al</strong> number will r<strong>et</strong>urn -1, O. or 1 according to wh<strong>et</strong>her the number<br />

is negative. zero. or positive. For a floating-point number. the result will be a floatingpoint<br />

number of the same fonnat with. one of the mentioned three vllhles_<br />

signum of a complex number is a complex number of the same phase but with unit<br />

magnitude. As a result. it will <strong>al</strong>ways be a complex number with floating-point<br />

components (see the discussion under abs, above).<br />

sin radians<br />

cos radians<br />

tan radians<br />

Standard trig functions. The number radians will be convened to a double-float if it is<br />

ration<strong>al</strong>. These accept complex arguments.<br />

asin number<br />

acos Ilumber<br />

asin r<strong>et</strong>urns the arcsine of the argument, and acos the arccosine. The result is in<br />

radians. number will be converted to a double-float first if it is ration<strong>al</strong>; it may <strong>al</strong>so be<br />

complex.<br />

Note that (asin -5), for instance, results in a complex answer.<br />

atan y &option<strong>al</strong> x<br />

Fairly standard arctangent<br />

With one argument (which may be complex). the arctangent is r<strong>et</strong>urned: for a noncomplex<br />

argument. the result is b<strong>et</strong>ween -fl/2 and '!T12 (exclusive). More gener<strong>al</strong>ly. the<br />

following definition is used:<br />

MC:<strong>NIL</strong>MAN:NUMBER 70<br />

23-DEC-83


Numeric Type Conversions 78 NIl. Manu<strong>al</strong><br />

atan(z) = -j.log( (l+i-z)-sqrt( 1/(I+z"2»)<br />

With two arguments. neither may be complex. . '111c arclangent of y / x is r<strong>et</strong>urned. and<br />

the signs of y and x arc used to derive quadrant information. Also. x may be zero as<br />

long as y is not lero. TIle result will be b<strong>et</strong>ween -." (exclusive) and 11 (inclusive).<br />

s 1 n h number<br />

cosh number<br />

tanh lIumber<br />

Hyperoolic·sine. cosine. and tangent. number m4ty be complex.<br />

as 1 nh IIlImber<br />

aeash Ilumber<br />

atanh lIumbi'r<br />

Etc.<br />

10.6 Numeric Type Conversions<br />

float Ilumba &optionaI other<br />

If olher is not supplied, then if number is a float of any type. it is r<strong>et</strong>urned: otherwise, it<br />

is con\'crted to a float of the default fonnat. which is currently double-float. but will be<br />

single-float in the future.<br />

If ollirr is supplied. then it must bea floating-point number. Ilumber is convened to a<br />

float of the same type. Thus.<br />

(float iTob o.orO)<br />

causes explicit conversion of frob to a single-float. Note that this will conven to a shoner<br />

fi)nn41t <strong>al</strong>so.<br />

The <strong>NIL</strong> compiler contrives to recognize the cases where float is given a constant ()ther<br />

argument. and caU speci<strong>al</strong> efficient routines for convening to the given type.<br />

rat 1ona1 number<br />

11lis converts number to . a ration<strong>al</strong> number. If it is <strong>al</strong>ready ration<strong>al</strong>. it is r<strong>et</strong>urned.<br />

Otherwise, a ration<strong>al</strong> number is computed corresponding to the precise representation of<br />

the number. For instance,<br />

(ration<strong>al</strong> (float 7/11 D.OsO» => 333637/524288<br />

It is <strong>al</strong>ways the case that for a floating-point number f,<br />

(= (float (ration<strong>al</strong> 1) 1) J) => t<br />

ration<strong>al</strong>ize number<br />

]f number is ration<strong>al</strong>, it is r<strong>et</strong>urned. Otherwise, the floating-point representation is taken<br />

to be an approximation of a ration<strong>al</strong> number, and that ration<strong>al</strong> number is r<strong>et</strong>urned. For<br />

instance.<br />

(ration<strong>al</strong>ize (float 7/11 O.OsO» => 7/11<br />

ration<strong>al</strong>ize is not the most efficient coercion routine around ...<br />

MC:NH.MAN:NUMBER 70<br />

23-DEC-83


•<br />

<strong>NIL</strong> Manu<strong>al</strong> 19 Integer Conversion and Speci<strong>al</strong>ized Division<br />

comp lex rea/parI &option<strong>al</strong> (imagpart 0)<br />

This constructs a complex number with re<strong>al</strong> part of rea/parI, and imaginary part of<br />

imagparl. If rca/parI is ration<strong>al</strong> and imagparl is either (integer) 0 or not supplied, then<br />

the result is just rca/pari. because complex numbers with ration<strong>al</strong> components and a zero<br />

imaginary part automatic<strong>al</strong>ly turn back. into ration<strong>al</strong> (non-complex) numbers. If either<br />

argument is floating-point. then both components will be converted to the longest floating<br />

point fnnnat of the two. For instance,<br />

(complex 5 3)<br />

(complex 1/5 3.0dO)<br />

(complex 2.510 0.750)<br />

(complex 2)<br />

(complex 2.0)<br />

=><br />

=><br />

=><br />

=><br />

=><br />

IIc(5 3)<br />

IIc(0.2dO 3.0dO)<br />

#c(2.510 0.710)<br />

2<br />

IIc(2.0 0.0)<br />

10.7 Integer Conversion and Speci<strong>al</strong>ized Division<br />

truncate /lumber &option<strong>al</strong> divisor<br />

t100r number &optionaJ divisor<br />

ce 111 ng /lumber &oplion.ll divisor<br />

round number &option<strong>al</strong> divisor<br />

These functions serve two similar purposes. They may be used to convert from a fioatingpoint<br />

number to an integer in various useful ways, and they can <strong>al</strong>so perfonn<br />

division/remainder operations similarly.<br />

If only one argument is given. it is converted to an integer by the appropriate m<strong>et</strong>hod:<br />

by truncation for truncate, by rounding towards negative infinity for floor, by rounding<br />

towards positive infinity for ceiling. or by rounding towards the nearest integer for round.<br />

(The <strong>NIL</strong>. and (,OMMO~ LISP round will round an exact h<strong>al</strong>f by rounding towards the even<br />

integer: in this it may differ from rounding in other languages.) Two v<strong>al</strong>ues are r<strong>et</strong>unled:<br />

the first is the result of the conversion, and the second is the remainder for the operation.<br />

If number is an integer. then the first v<strong>al</strong>ue is that integer and the second is O. If it is a<br />

ratio. then the second will <strong>al</strong>so be a ratio, and if it is a float, then the second will bea<br />

float of the same fonnat. For example,<br />

MC:<strong>NIL</strong>MAN:NUMBER 70<br />

23-I)EC-83


Integer Conversion and Speci<strong>al</strong>ized Division so <strong>NIL</strong> Manu<strong>al</strong><br />

(truncate 2.5) => {2, D.5}<br />

(truncate 5/2) => {Z. lIZ}<br />

(truncate -Z.5) => {-2. -O.5}<br />

(truncate -5/2) => {-Z, -lIZ}<br />

(ceiling 2.5) => {3. -0.5}<br />

(ceiling 5/2) => {3, -I/2}<br />

(ceiling -2.5) => {-Z, -O.5}<br />

(ceiling -5/2) => {-2, -1/2}<br />

(floor 2.5) => {2.·0.5}<br />

(floor 5/2) => {2. 1/2}<br />

(floor -Z.5) => {-3. 0.5}<br />

(floor ,-5/2) => {-3. lIZ}<br />

(round 2.5) => {2. 0.5}<br />

(round -Z.5) => {-Z, -O.5}<br />

(round Z.6) => {3. -O.4}<br />

(round -2.6) => {-3, 0.4)<br />

(round 3.5) =>' {4. -0.5)<br />

(round -3.5) => {-4, O.5}<br />

If the divisor argument is given .. the first v<strong>al</strong>ue is the result of integer conversion of the<br />

result of dividing /lumber by divisor, after the appropriate type of rounding or truncation<br />

is performed. The second v<strong>al</strong>ue is the remainder for that division after the<br />

rounding/truncation. That is. if the v<strong>al</strong>ues arc q and r. then<br />

{:; nUlI/otlr (T i- q divisor) r) j => t<br />

For instance~<br />

(truncate 5 2)<br />

(truncate -5 2)<br />

(truncate 5 -2)<br />

(truncate -5 -2)<br />

(floor 5 2)<br />

(floor -5 2)<br />

(floor 5 -2)<br />

(floor -5 -2)<br />

=><br />

=><br />

=><br />

-><br />

=><br />

-><br />

-><br />

=><br />

{2,<br />

{-2.<br />

{-2.<br />

{2.<br />

{2.<br />

{-3.<br />

{-3 t<br />

{2,<br />

I}<br />

-I}<br />

I}<br />

-I}<br />

I}<br />

I}<br />

-I}<br />

-I}<br />

What this means is. if truncate is given two integer arguments. then the two v<strong>al</strong>ues are<br />

the quotient and remainder. as obtained by those functions. If floor is given two integer<br />

arguments. then the second v<strong>al</strong>ue is the standard mod (page 81).<br />

rem number divisor<br />

When rem is given integer arguments. it is identic<strong>al</strong> to the MACLISP remainder function.<br />

More gener<strong>al</strong>Jy. however. it perfonns the truncate operation on its two arguments, and<br />

r<strong>et</strong>urns the second v<strong>al</strong>ue from that as its v<strong>al</strong>ue.<br />

rema 1 n de r number divisor<br />

This is identic<strong>al</strong> to rem. The name is r<strong>et</strong>ained for MAClISP compatihility: if number and<br />

dil'isor arc both integers (which is aU the MACl.ISP remainder function accept~). then the<br />

op~r<strong>al</strong>ion is the same.<br />

MC:NII.MAN:NUMBER 70<br />

23-DEC-83


Nil. Manu<strong>al</strong> 81 l.ogicaJ Operations on N urn hers<br />

One slight discrepency exists with the MACl.ISP remainder function: in MAC"I lSI>'<br />

remainder wiJ] accept a Jil'isor argument of 0 and r<strong>et</strong>urn number. This is incompatible<br />

with the definition of rem (and <strong>al</strong>so with fixnum open-compilation of remainder in<br />

MACl.ISJ>!) because of the implicit division involved-in <strong>NIL</strong>, a divisor of 0 results in a<br />

division-by-zero error.<br />

mod number divisor<br />

When Ilumber and divisor are both integers, then mod is the stmdard "modulus" function.<br />

More gener<strong>al</strong>ly. mod perf0l111S the floor operation on its two arguments, and r<strong>et</strong>urns the<br />

second v<strong>al</strong>ue from that as its v<strong>al</strong>ue.<br />

Note that by \'irtue of its definition in terms of floor which is a kind of division. a<br />

divisor of zero results in a division-by-zero error.<br />

ffloor Ilumber &option<strong>al</strong> divisor<br />

ftruncate Ilumber &option<strong>al</strong> divisor<br />

fee 111 ng I1wllber &option<strong>al</strong> divisor<br />

fround Ilumber &option<strong>al</strong> divisor<br />

These functions behavc just like floor. truncate. ceiling, and round. except that the first<br />

v<strong>al</strong>ue r<strong>et</strong>urned is converted to a float if it is not. While this is fairly useless for ration<strong>al</strong><br />

arguments. it can rcsult in some efficiency gain for arguments of type float. Note that if<br />

both arguments are ration<strong>al</strong>. only the first v<strong>al</strong>ue will be a double-float, not the second.<br />

10.8 Logic<strong>al</strong> Operations on Nuntbers<br />

The logic<strong>al</strong> operations in this section treat integers as if they were represented in two'scomplement<br />

notation.<br />

One common use of integers in this manner is as s<strong>et</strong>s; each bit which is "on" (is 1) in the<br />

integer represents the presence of a particular item in the s<strong>et</strong>. If the integer is negative. then it is<br />

an infinite s<strong>et</strong>. because the sign is vinu<strong>al</strong>ly extended to infinity. The presence of a particular item<br />

in a s<strong>et</strong> can be tested for with logbitp; one refers to the item by its lero-origined bit index.<br />

Other s<strong>et</strong> operations can be perfonned with the various boolean functions: log and performs<br />

intersection, logior performs union, logxor performs s<strong>et</strong>-exclusive-or, and logandc2 performs<br />

s<strong>et</strong>-difference. A new s<strong>et</strong> with an item represented by bit-index index added can be constructed<br />

by a form like<br />

(dpb 1 (byte 1 index) integer)<br />

10gb1tp index integer<br />

logbitp is true if the bit in integer whose index is index (that is, its weight is (expt 2<br />

index» is a one-bit; otherwise, it is f<strong>al</strong>se.<br />

1 og 1 0 r &rest integers<br />

logxor &rest illtegers<br />

10gand &rest illtegers<br />

logeqv &rest integers<br />

These r<strong>et</strong>urn the bit-wise logic<strong>al</strong> inclusive or, exclusive or, and, or equiv<strong>al</strong>ence (<strong>al</strong>so<br />

known as exclusive 110r) of their arguments. ]f no arguments are given, the results are 0<br />

MC:<strong>NIL</strong>MAN:NUMBER 70<br />

23-DEC-83


I #ogic<strong>al</strong> Opcrations on Numbers 82 <strong>NIL</strong> Manu<strong>al</strong><br />

for logior and logxor. and -1 f()r log and and logeqv. which are the identities for those<br />

operations, Notc <strong>al</strong>so t.he fixllum-unly versions of these. logior&. logxor&. logand&. and<br />

logeQv& (page 88).<br />

lognand integerl illteger}<br />

lognor il/legerl integer2<br />

logandcl integerl integer}<br />

logandc2 il1Iegerl integer]<br />

logorc1 ilJlrgt'rl integerl<br />

1 ogorc2 iIlTt!~crl integer2<br />

Th~se are the other six n()n·trivi~fl bit-wise logic<strong>al</strong> operations on two arguments. Bec~luse<br />

they arc not commutative or associative. they take exactly two arguments rather than any<br />

number.<br />

The "cl lt and "c2" in some of the above names should be read as "having complemented<br />

argument 1 (ur 2)": for instance. logorc1 is the logic<strong>al</strong> or of the logic<strong>al</strong> complement of<br />

illtcgerl. with ituegerl.<br />

logandc1 and logandc2 are often used as bit-deuring functions. Howe\er. the ordering<br />

given to such names as bit-clear or logelr is often confusing (and historic<strong>al</strong>ly. has b~n<br />

incompatible from one macro-package to another), togandc1 r<strong>et</strong>urns inTeger2 with aU bits<br />

which are on in illlegerl. cleared; logandc2 r<strong>et</strong>urns integerl. after dearing any bits<br />

which are s<strong>et</strong> in illIeger2.<br />

boo 1 e up inlegerl illteger2<br />

'Jbe function boo'e takes an operation op and two integers. and r<strong>et</strong>unlS an integer<br />

produced by perfonning the logic<strong>al</strong> operation specified by op on the two integers.<br />

There are sixteen variables (the names of which are listed below) which have the boolean<br />

functions as their v<strong>al</strong>ues; the boolean functions are represented as fixnums from 0 to IS<br />

(inclusive).<br />

The <strong>NIL</strong> implementation of boole defines the boolean functions such that they map into<br />

the standard "truth table" used in MACUSP. lbat is, if the binary representation of op is<br />

abed. then the truth table for the boolean operation is<br />

y<br />

101<br />

x<br />

o I a c<br />

I<br />

1 I b d<br />

For example, the boolean function 4 has binary representation 0100. This shows that the<br />

result will have a bit s<strong>et</strong> only when the corresponding bit of integer] is 1 and integer2 is<br />

O. This is the logandc2 operation. New code, . especi<strong>al</strong>ly that intended to b<strong>et</strong>ransponed<br />

b<strong>et</strong>ween COMMON LISI) implementations. should nel'er rely on this-this coincidence is<br />

provided 01111' for M:\CLlSI' compatibility.<br />

MC:<strong>NIL</strong>MAN;NUMRER 70<br />

23-DEC-83


...<br />

Nil. Manu<strong>al</strong> 83 I.ogic<strong>al</strong> Operations on Numbers<br />

Also for !\.1ACI.lSP compatibility. when Nil. boole receives more than three arguments. it<br />

goes from left to right. thus:<br />

(boole k x y z) (boole k (boole k x y) z)<br />

In certain cases it may accept less than three arguments. Again. new code should not rely<br />

on this behaviour.<br />

lognot inleger<br />

R<strong>et</strong>urns the bit-wise logic<strong>al</strong> 1101 of its argument. Every bit of the result is the complement<br />

of the corresponding bit in the argument.<br />

1 ogtes t illlcgcr/ int('g('r]<br />

logtest is a predicate which is true if any of the bits designated hy the l's in ilJlrgerl arc<br />

l's in integer 2.<br />

(logtest x y) (not (zerop (logand x y»))<br />

except that it can be done more efficiently. because it docs not have to actu<strong>al</strong>ly compute<br />

the logand.<br />

ash intrger coUIll<br />

Shifts in/('gcr arithmctic<strong>al</strong>ly left by COUllt bit positions if COUllt is posltl\'e. or right -COUIlI<br />

bit positions if cOUll1 is ncgative. The sign of the result is <strong>al</strong>ways the same as the sign of<br />

integer.<br />

The actu<strong>al</strong> implementation of ash works on. and will produce. bignums. There is <strong>al</strong>so an<br />

A~hR n.1nftion which de<strong>al</strong>s (In!y with fixnums.<br />

In practice. COUllt is only <strong>al</strong>lowed to be a fixnum ...<br />

logcount i11leger<br />

If integer is non-negative. logcount r<strong>et</strong>urns the number of "1" bits on in its twoscomplement<br />

representation. If it is negative, then the number of "0" bits in that<br />

representation is r<strong>et</strong>urned; this is then the same as the count of "Itt bits in the logic<strong>al</strong><br />

complement of it<br />

integer-length integer<br />

integer-length r<strong>et</strong>urns the zero·origined index of the sign bit of the field needed to<br />

represent integer in twos-complement notation. That is, any integer i may be represented<br />

in twos-complement notation in a field (1 + (integer-length i» long. If integer is non·<br />

negative, then it may be represented in unsigned binary fonn in a field (integer-length<br />

integer) long. For instance,<br />

(integer-length 5) => 3<br />

because the binary representation of 5 is ... 0101.<br />

The following two functions are provided for MACLISP compatibility. They both do some<br />

semblance of manipulation of the binary representation of integers. However, the results of these<br />

functions are defined in tenns of the absolute v<strong>al</strong>ue of the integer they are examining-because in<br />

Nil. integers are oriented towards manipulation of their twos·complement representation. these<br />

routines may not be panicularly efficient on negative integers.<br />

MC:NI1.MAN:NUMBER 70<br />

23-DEC-83


t<br />

Byte Manipulation Functions 84 Nil. Manu<strong>al</strong><br />

haulong integer<br />

R<strong>et</strong>urns the number uf signific,mt bit~ in lheabsolule v<strong>al</strong>ue of illteger. The precise<br />

computltion performed is ceilillg(1og2(abs(illteger)+ 1».<br />

For example:<br />

(haulong 0) => 0<br />

(haulong 3) => 2<br />

(haulong 4) => 3<br />

(haulong -7) => 3<br />

haulong is provided ft'r MAfTISP c(}m~~ttibility:<br />

prefer~nce.<br />

. integer-length should be used in<br />

ha 1 part integer COUIlI<br />

This function exists primarily for MACI.lSP cumpatibility. Its function<strong>al</strong>ity is subsumed by<br />

the byte manipulation functions Idb and dpb. which are described in the following<br />

section ..<br />

haipart r<strong>et</strong>urns the high COUIlI bits of the binary representation of the absolute v<strong>al</strong>ue of<br />

integer. or the low -('mlllt bil~ if COUII( is negative.<br />

10.9 Byte l\1anipulation Functions<br />

There are various functions in <strong>NIL</strong> and CO!\'1 MO~ LISP to de<strong>al</strong> with arbitrary-width contiguous<br />

fields of bite; within integers. These functions are not restricted to operations on fixnums. but<br />

rather de<strong>al</strong> with the twos-complement representation of arbitrarily large integers.<br />

Most of these functions use an object c<strong>al</strong>led a byte specifier. This object is used to refer to a<br />

field within an integer. which is dctennined by the size of the field. and the' positioll of the field<br />

within an integer. Both of these must be non-negative integers.<br />

byte size position<br />

byte constructs a byte specifier. You may not depend on the fonnat of the object<br />

r<strong>et</strong>urned. only that it wi]) be acceptable for usc as a byte specifier by the fonowing<br />

functions; in particular. the type of the object r<strong>et</strong>urned by byte may not be distinct. In<br />

gener<strong>al</strong>. the restrictions on the magnitude of size and posilion are implementation<br />

. dependent. In <strong>NIL</strong>, they may be any non-negative fixnums. Byte specifiers in which the<br />

size and position will both fit in an unsigned field 15 bits long (that is. they are both<br />

integers from 0 to 32767 inclusive) are represented more efficiently than others.<br />

byte - size bylespec<br />

byte-pos it ion bylespec<br />

byte-size r<strong>et</strong>urns the size "component" of bylespec, and byte-position r<strong>et</strong>urns the<br />

position "component".<br />

MC:NIl.MAN;NUMBER 70<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 85 Byte Manipulation Functions<br />

1 db bytespec ill1eger<br />

by/{'sl'('c specifics a field of integer to be extracted. That field extracted from the twoscomplement<br />

binary representation of illlegrr is r<strong>et</strong>urned as a non-negative integer. For<br />

instance. the low three bits can be extracted using the byte specifier constructed by (byte<br />

3 0):<br />

(ldb (byte 3 0) 15) => 7 :15is ... OlllIll in binary<br />

( 1 db (byte 3 0) 14) => 6 ; 14 is ... 011Ill0 in binary<br />

( 1 db (byte 3 0) -3) => 5 ;-4 is ...1111101 in binary<br />

The third group of three bilS can he extracted lIsing tJ1C byte specifier (byte 3 6):<br />

(ldb (byte 3 G) 15) => 0 :15is ... OOOOlll111inbinary<br />

(ldb (byte 3 6) 63) => 7 :6Jis ... Olllll1111inhinary<br />

(ldb (byte 3 6) -3) => 7 ;-3is ...lll1111101 in binary<br />

Idb may be used with s<strong>et</strong>f (page 38). if the fonn illfeger is a \'aJid 1'1£1('r argument to<br />

's<strong>et</strong>f. Rather than modifying the integer itself. doing s<strong>et</strong>f on a Idb fonn will "nest" like<br />

( s<strong>et</strong> f (1 db bytcspcc i11lrger) newbyte)<br />

==><br />

(Sf.:c,;,f integer (dpb newbyte bytespec integer»<br />

ldb-test bytespec integer<br />

( 1 db - te S t bytespec integer)<br />

(not (zerop (ldb bylespec integer»)<br />

While a Idb -test can in gener<strong>al</strong> be . done more efficiently than the second filnn.<br />

pr\ibat1y i5 not dl.HK ~f'Cddliy y<strong>et</strong> ii} j~iL<br />

it<br />

dpb newbyte bytespec integer<br />

dpb is sort of the inverse of Idb. It r<strong>et</strong>urns an integer with the same binary<br />

representation as illtrgrr. except that the field referred to by by1rspec is replaced by the<br />

twos-complement binary represention of newbyte.<br />

(dpb 3 (byte 3 0) 0) => 3<br />

(dpb 7 (byte 3 0) 0) => 7<br />

(dpb 0 (byte 3 0) -1) => -8<br />

mask-field bycespec integer<br />

This does not seem to be in yell<br />

mask -field r<strong>et</strong>urns an integer whose binary representation is an zeros, except in the field<br />

referred to by bylespec, which has the same bits as that field in integer. That is,<br />

(mas k -f i e 1 d bytespec integer)<br />

<br />

( d P b (1 db bytespec integer) bytespec 0)<br />

<br />

(ash (1 db bytespec integer) (byte-pos ; ti on bytespec»<br />

If the integer is being used as the representation of a s<strong>et</strong> (section 10.8. page 81). then<br />

mask-field could be considered to be perfonning an intersection operation on the s<strong>et</strong><br />

represented by integer. and the s<strong>et</strong> of <strong>al</strong>l objects whose bit positions correspond to the<br />

positions within the fic1d specified by bytespec.<br />

MC:<strong>NIL</strong>MAN:NUMBER 70<br />

2J-DEC-83


R~andom Numbers<br />

86 <strong>NIL</strong> Manu<strong>al</strong><br />

de pos 1 t - f 1 e1 d 1I(' •...t~",e<br />

This docs 110/ SCt'lIt 10 be ill ),el?<br />

by/t'sp('c integer<br />

This is the "inverse" of mask-fieJd. deposit-byte r<strong>et</strong>urns an integer which is the same<br />

as inlcgcr, except that the field referred toby bylespec is contains instead the bYlespec<br />

field of IJfwbyle. That is. it is like<br />

(dpb (1 db bytespec newbyle) bylespec integer)<br />

10.10 Random Numbers<br />

random &option<strong>al</strong> modulus random-sl<strong>al</strong>e<br />

I f no modulus argument is given. then this is compatible with the MAC'I.ISP. random<br />

function of no arguments: it r<strong>et</strong>urns a number mndomly distributed over the range of <strong>al</strong>l<br />

fixnums. (CO\fMO;\ J IS}> docs not define random nfnn argumenL~.) Otherwise. the<br />

answer r<strong>et</strong>urned by random is n number of the ~lme type evenly distributed b<strong>et</strong>ween zero<br />

(inclusive) and modulus (exclusive).<br />

If random-sl<strong>al</strong>c is supplied. it must be an object of type random-state: tIlis is what<br />

holds the SUIte of the random number generator. If it is not supplied. then the glob<strong>al</strong><br />

random number SL'lte (the v<strong>al</strong>ue of *random-state.) is used.<br />

The random number r<strong>et</strong>urned is random over tta11 its bits": random-sl<strong>al</strong>e is used to<br />

compute a sequence of random bilS which are used· to construct the result. For a floatingpoint<br />

number. this is used as tile significand (fraction) of a constnlcted number which is<br />

sc411cd to the appropriate range: filr an integer. a sequence of bit'i is constructed<br />

approximately 10 bilS longer than that needed for the resul~ and then a modulus<br />

operation performed.<br />

*random-state*<br />

Variable<br />

This holds the glob<strong>al</strong> random state used by default by random. One may. for instance,<br />

lambda-bind this variable to a new object of type random-state to save and restore the<br />

state of the random number generator.<br />

make-random-state &option<strong>al</strong> slate<br />

This creates a new random-state object If sl<strong>al</strong>e is nil or not suppJied. then a copy of<br />

the current v<strong>al</strong>ue of *random-state* is r<strong>et</strong>urned. Ifs/<strong>al</strong>e is t. then a new random-state<br />

is r<strong>et</strong>urned. seeded from the time. Otherwise, Slate should be a random-state; its state<br />

is copied.<br />

When <strong>NIL</strong> is first loaded up. the random-st<strong>al</strong>e object in .random-state* is <strong>al</strong>ways in the<br />

same state. It may be seeded from the current time by doing<br />

(s<strong>et</strong>q .random-state. (make-random-state t»<br />

jf . that is necessary for applications. There is, however.. no offici<strong>al</strong>1y defined way to g<strong>et</strong> a<br />

"known" random-state from which the same sequence of pseudo-random numbers may be<br />

generated. other than copying one withmake-random-state and saving it. If this is found to be<br />

necessary (for instance to reproducibly debug a program which uses the random number<br />

generator). the fonn<br />

MC:<strong>NIL</strong>MAN:NUMBER 70<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 87 Fixnum-Onty Arithm<strong>et</strong>ic<br />

(si:make-random-state-intern<strong>al</strong>)<br />

wilt create a new random-state the same as the one i'\IL starts up with.<br />

For MAC'USP compatibility, the random option to the status and sstatus macros is supported.<br />

(status random) r<strong>et</strong>urns a copy of thc current v<strong>al</strong>ue of .random-state-: (sstatus random<br />

random-st<strong>al</strong>e) restores .random-state- to a copy of that. Onc may <strong>al</strong>so reseed by doing (sstatus<br />

random integer).<br />

10.11 Fixnum-Only Arithm<strong>et</strong>ic<br />

Currently. the :'\11. compiler does not make any usc of lype declarations to help it decide to<br />

inline-code arithm<strong>et</strong>ic routines. Primarily for this reason. !'IL provides a full complement of<br />

fixllum-only and double-fioat-only arithm<strong>et</strong>ic rOlltines. which will be in1ine-coded by the compiler<br />

(when possible and reasonable) into fairly efficient code.<br />

In Nil., as in MACIISP. the tot<strong>al</strong>ly open-~ompi1ed fixnum-only routines behave "as the machine<br />

docs": that is. overflow is gener<strong>al</strong>ly not d<strong>et</strong>ected. Note that thc VAX hardware d<strong>et</strong>ects division by<br />

zero. howcver. and those routines not compiled as machine instructions. sllch as "&. may d<strong>et</strong>ect<br />

overflow and signa1 an crror.<br />

10.11.1 Comparisons<br />

-!r number &rcsl more-numbers<br />

1-& number &rest more-numbers<br />

& number &rest morc-numbers<br />

< -& number &rest mcire-llumbers<br />

>-& number &rest more-numbers·<br />

Fixnum-only versions of the =. 1=.


Fixnum-Only Arithm<strong>et</strong>ic 88<br />

.& &rest fixllums<br />

Fixnum-only multiplication.<br />

1& fixllum &rest more-jixIlulIls<br />

Fixnum-only division. With one ,lrgument. reciprocates. which seems singularly useless to<br />

me~ since this is truncating division. reciprocation is an error if the argument is lero~ one<br />

if it is one, otherwise zero.<br />

\& jixlluml jixIlum2<br />

Fixnum-only remainder. Although there is no CO\4MON I.ISP \ function to make the<br />

fixllum-only (as inherited from MACI.JSP) \ function change incompatihly. the name of \<br />

is heing changed to \& for consistency. Note that this function mllst nonn<strong>al</strong>ly he typed<br />

in as \ \&. bec<strong>al</strong>lse \ is the "quoting" character in NH_<br />

1+& ji.'Jmum<br />

1-& jixllum<br />

Fixnum-only "I + and 1 -.<br />

ab $& jixflum<br />

Fixnum-only abs.<br />

s1gnum& jixnum<br />

Fixnum-only signum.<br />

"& jixllum I jixIlum2<br />

Fixnum-only expt. It is an error for the result to exceed the range representable by a '<br />

fixnum.<br />

10.11.3 Bits and Bytes<br />

logand& &rest fixnums<br />

logior& &rest jixnums<br />

logxor& &rcst jixnum<br />

logeqv& &rcst jixnums<br />

lognand& fixnuml jixnum2<br />

lognor& jixllumJ fixnum2<br />

logandcl& jixn:JmJ jixnum2<br />

logandc2& jixllumJ jixIZum2<br />

logorcl& jixllumJ fixnum2<br />

logorc2& jixnumJ fixnum2<br />

Fixnum-only boolean functions<br />

boo 18& op jixnuml jixnum2<br />

Fixnum-only boole.<br />

MC:<strong>NIL</strong>MAN:NUMBER 70<br />

23-DEC-83<br />

. . ;. , .' ~<br />

~ . . ~ .~ ... ~ ~~<br />

'~. ': " ~, : ,',,'" ,',,-."" . ."'.. '~'" "':" :,'::', '. '.~. .'~::"" '.,~", . ',.<br />

' .~'


<strong>NIL</strong> Manu<strong>al</strong> 89 Fixnum-Only Arithm<strong>et</strong>ic<br />

lognot& fixllum<br />

Fixnum-only lognot.<br />

logtest& fixl1uml fixIlum2<br />

Fixtlum-only logtest.<br />

logb1tp& index fixllum<br />

Fixnum-only logbitp. 'Ibis is defined for an index larger than the number of bits in a<br />

fixnum: however. inc/ex must he a fixnum.<br />

as h& fixl1um COUllt<br />

Fixnllm-only ash. Shifting hy a positive C()ulll may shift hil~ into the sign pOSItIOn, tJ1US<br />

changing me sign of the result (and losing bits). It is an error if COUll I is not of type<br />

(signed-byte 8). tJ,at is, b<strong>et</strong>ween -128 and 127 inclusive.<br />

logcount& fixllum<br />

Not y<strong>et</strong> in?<br />

haulong& jixl1ulll<br />

Not inHne-coded. but provided for compl<strong>et</strong>eness (sec. perhaps. %fixnum-haulong. (noty<strong>et</strong>-written».<br />

Maybe this should he diked. since haulong should dispatch just as rapidly.<br />

1 db& bytcspcc fixllum<br />

Fixnum-only Idb. This is not strictly a version of generic Idb which takes a fixnum<br />

second argument. but ramer a version of low-level fixnum byte-extraction which takes a<br />

gener<strong>al</strong> bytespec as an argument: it is an error for the byte to extend outside of the<br />

fixnum (for the position plus the size of the bytespec to be greater than 30).<br />

dpb& ncwby/e by/espcc fixllum<br />

As Idb& is to Idb. so dpb& is to dpb. Other Idb& restrictions apply.<br />

s<strong>et</strong> -1 db& bylespec jixnum newbyte<br />

Maybe this shouldn't be here, but it is in case s<strong>et</strong>f g<strong>et</strong>s used on Idb&.<br />

Back in the olden days when there were few thoughts about integers greater than 34359738367<br />

(or som<strong>et</strong>hing like that), the byte-specifier to Idb and its friends used to be designated as ppss.<br />

The interpr<strong>et</strong>ation of this is that. if you consider ppss to be a 4-digit oct~l number, the number<br />

(oct<strong>al</strong>) pp tells the position of the byte being referenced, and the ss the size. In order that a byte<br />

specifier not be so restricted in the size of the "byte" it is referencing (since the pp can be<br />

upwards-compatibly extended to the left but the ss cannot). <strong>NIL</strong> has incompatibly abandoned that<br />

fonnat. So that code which uses this old fonnat may be trivi<strong>al</strong>ly converted. however, the old<br />

function<strong>al</strong>ity may be obtained with the %Idb and %dpb functions. below.<br />

Xl db ppss jixnum<br />

Extracts the byte defined by ppss (as described above) from fixllum. It is an error if the<br />

byte so referenced lies outside of the fixnum (that is, the size plus the position is greater<br />

than 30).<br />

MC:<strong>NIL</strong>MAN:NUMBER 70<br />

23-DEC-83


I )ouhle-Float-Only Arithm<strong>et</strong>ic 90 <strong>NIL</strong> Manu<strong>al</strong><br />

%dpb v<strong>al</strong> PI'SS fi"lIlU1l1<br />

R<strong>et</strong>urns a fixnum which is firnulI1 with the byte defined hy ppSS replaced by the fixnum<br />

v<strong>al</strong> (truncated as necessary). It is an error if the byte so referenced lies olltside of the<br />

fixnum (that is. the size plus tJ1C position is greater tJlan 30).<br />

10.11.4 The Super-Primitives<br />

G<strong>et</strong>ting closer still to thc hardware ...<br />

load-byte fixIIU1I1 POSiliol1 sizl'<br />

This is thc primitive f'1I eXlract-a-byte-from-a-fixnum function. In the style of many ~II.<br />

primitivcs. and in the style of the VAX byte-extracting instructions, it takcs arguments of<br />

position and size (different ordering from the byte function). It is an error for the byte<br />

dcscrib~d by posi/ioll and size to lie out of hounds of the intern<strong>al</strong> reprcsentation of a<br />

fixnum (30 bits).<br />

depos i t-byte jiXIIUII1 P(}SIlIOII size llewbYIe<br />

Modifics tJ1C byte. as per load-byte. Note argument ordering is different from dpb in<br />

that I1l'wbyle comes last 'Ibis is to make it convenient fbr s<strong>et</strong>f to usc.<br />

sys :Xf1xnurn-plus-w1th-overflow-trapp1ng x y overflow-code ...<br />

sys: Xf1xnum-d1 fference-w1 th-overfl ow-trapping<br />

Speci<strong>al</strong>/onn<br />

x y O\'erflow-code .•.<br />

sys :Xf1xnum-t1mes-w1th-overflow-trapp1ng x Y Ol'crflow-code ...<br />

sys : Xf 1xnum- as h -wi th-oYerflow-trapp 1 ng x )' ovclfloM/.codc ...<br />

lbese are speci<strong>al</strong> fonns which primarily exist for the benefit of implementing generic<br />

arithm<strong>et</strong>ic functions. The appropriate binary operation on x and y, inJine-coded. is<br />

pcrfonned: jf afterwards mere has been no o\'erflow, that result is r<strong>et</strong>urned. Otherwise,<br />

ol'erflo~code is run, and the resultant v<strong>al</strong>ue r<strong>et</strong>urned.<br />

Only the compiler knows how to use these right now.<br />

10.12 Double-Float-Only Arithm<strong>et</strong>ic<br />

<strong>NIL</strong> provides some functions (like those in MACLISP) which operate only on double-floats. It is<br />

unlikely that corresponding functions wi]) be provided for other floating-point types when thcy are<br />

added, however; inJine-codcd arithm<strong>et</strong>ic on such numbers will be handlcd by declarations to the<br />

compiler eventu<strong>al</strong>ly.<br />

+$ &rest double-floats<br />

• $ &rest double-floats<br />

-$ double-float &rcst more-double-floats<br />

IS double-float & rest more-double-floats<br />

1+$ double-floQt<br />

1-$ double-flo<strong>al</strong><br />

Double-float-only stuff. Essenti<strong>al</strong>ly this is maclisp-compatible.<br />

MC:<strong>NIL</strong>MAN;NUMHER 70<br />

23-DEC-83


•<br />

<strong>NIL</strong> Manu<strong>al</strong> 91 Decompusition of Flo<strong>al</strong>ingPoint Numbers<br />

abs$ double-float<br />

l)ouble-Hoat-onty abs.<br />

max$ &rest double-floats<br />

mi n$ &rest duuble-floots<br />

... s double-float jixl1um<br />

The double-fimlt only exponentiation function.<br />

10.13 Decomposition of Floating Point Numbers<br />

All of the following routines are defined by CO\IMON LISP. The basic premise is that a<br />

floating point numheris represented by some number of digits in a base b. multiplied by b to<br />

some exponent. with a sign. In <strong>NIL</strong> on the VAX. b is of c()urse2 for the primithc floating-point<br />

data types. so the exponent is a binary exponent.<br />

float-radix float<br />

This r<strong>et</strong>urns the radix b of float. For the I'll. prllnltlve float daL1 types (short-float.<br />

single-float. double-float. and long-float). it <strong>al</strong>ways r<strong>et</strong>urns 2.<br />

decode-float float<br />

This function r<strong>et</strong>urns three v<strong>al</strong>ues:<br />

(I) 'Ibc sigllijic<strong>al</strong>ld of flo<strong>al</strong>. This is· a number b<strong>et</strong>ween 1/ b (inclusive) and 1<br />

(exclusive). which represents the bits of .POOI. The sole exception is for zero. for<br />

which the r<strong>et</strong>urned significand is l.ern (of the ~1me floating-point type as floa!).<br />

(2) The exponent of float. This is· an integer which. jf used to sc<strong>al</strong>e thc significand<br />

(using sc<strong>al</strong>e-float. bclow), will produce a number with the same absolute v<strong>al</strong>ue<br />

as float.<br />

(3) The sign of float; this is either 1.0 or -1.0, in the same floating-point fonnat as<br />

float.<br />

Thus.<br />

(multiple-v<strong>al</strong>ue-bind (significand exponent sign)<br />

(decode-float float)<br />

{= float (* (sc<strong>al</strong>e-float significand exponent) sign»)<br />

=> t<br />

sc<strong>al</strong>e-float float integer<br />

This is like doing<br />

(. float (expt b integer»<br />

where b is the radix of float. It is done, of course. somewhat more efficiently and<br />

without danger of any son of intennediate overflow or underflow if the fin<strong>al</strong> rcsultcan be<br />

represented. It is an error if the fin<strong>al</strong> result cannot be represented; sc<strong>al</strong>e-float will sign<strong>al</strong><br />

an error. (In a future <strong>NIL</strong> with a smaner compiler and type declarations, however, it may<br />

be the case that open-compilation of this function will not sign<strong>al</strong> an error.)<br />

1n05e familiar with the PDPIO MACLISP fsc function will recognize this as being somewhat<br />

of the same thing, <strong>al</strong>though it is not subject to the kludges that fsc is (partly because the<br />

VAX docs not represent unnonn<strong>al</strong>ized floating point numbel'$} ..<br />

MC:<strong>NIL</strong>MAN;NUMRER 70<br />

23-DEC-83


,; ~:..-<br />

Implementation Constants 92 Nil. Manu<strong>al</strong><br />

float-sign float &option<strong>al</strong> other<br />

If other is not supplied. then this r<strong>et</strong>urns the sign of float. 1;0 or -1.0. in the same<br />

fonnat as float. This is the same as the third v<strong>al</strong>ue r<strong>et</strong>urned by decode-float.<br />

If <strong>al</strong>her is supplied. then the effcct is of transfering the sign of flo<strong>al</strong> to other; the result<br />

will be of the same floating-point format and absolute v<strong>al</strong>ue as oliler. but have the same<br />

sign as flo<strong>al</strong>.<br />

float-digits flo<strong>al</strong><br />

This r<strong>et</strong>urns the number of base b digits in the representation of flaa/. In ~II.. this is a<br />

conswnt for any particular one of the primitive floating-point lypes. Specific<strong>al</strong>ly. shortfloat<br />

has 19. single-float has 24. double-float has 56, and long-float has 128.<br />

float-precision flo<strong>al</strong><br />

This (he said while looking the other way) is the same as float-digits except that it<br />

r<strong>et</strong>urns 0 for zero.<br />

1ntagar-decoda-float float<br />

This r<strong>et</strong>urns three v<strong>al</strong>ues. like decode-float. The difference is that the significand is<br />

r<strong>et</strong>urned as an integer, and the exponent differs accordingly. The magnitude of the<br />

integer is such that it is b<strong>et</strong>ween "2"p (exclusive), and 2 .... (p-1) (inclusive), wherep is the<br />

precision of float (as would be r<strong>et</strong>urned by float-precision). If the float radix is 2 as it is<br />

for the <strong>NIL</strong> primitive floating types. then the integer will have the same number of bits<br />

(intAgAr-IAnnth l';le(' 8) ~~ the rr{'d~ilJn. Again. an ~xccption for zero exists: the first<br />

v<strong>al</strong>ue will then be O.<br />

10.14 Implementation Constants<br />

most-positive-f1xnum<br />

Cons~nt<br />

most-negat1ve-fixnum<br />

Constant<br />

lbese have as their v<strong>al</strong>ues the most positive and negative fixnums representable in <strong>NIL</strong>;<br />

integers of the same sign but greater magnitudes have to be represented as bignums.<br />

Because <strong>NIL</strong> uses twos-complement representation for fixnums, the absolute v<strong>al</strong>ue of<br />

most-negative-fixnum is one greater than most-positive-fixnum.<br />

most-pos it iva-short-float<br />

Constant<br />

most-pos it ive-s1 ngle-float<br />

Conslant<br />

most-pos it i ve-doubla-fl oat<br />

Constant<br />

most-pos it iva-long-float<br />

Constant<br />

These have as their v<strong>al</strong>ues the most positive numbers of the corresponding fonnats which<br />

can be represented.<br />

most-negat i ve-short-fl oat<br />

Constant<br />

most-negat 1ve-si ngle-float<br />

ConstGnt<br />

most-nagat iva-double-fl oat<br />

'Constanl<br />

most-nagat iva-long-float<br />

COllslant<br />

lbcse have as their v<strong>al</strong>ues the most negative numbers of the corresponding fonnats which<br />

can be represented.<br />

MC:<strong>NIL</strong>MAN;NUM8ER 70<br />

23-DEC-83<br />

.. t -,.-c,... ~ • .... ......... ".4...... •<br />

~~» ~ ~~-: ~-~~~~ ?- ~ ~. ~<br />

"- ~ - ... ~ .'"


as<br />

NIl. Manu<strong>al</strong> 93 Implementation Constant')<br />

18ast-pos 1 t 1ve-short-float COllsl<strong>al</strong>l1<br />

1 east-pos 1 t 1 ve-s 1 ng1 e-f1 oat C0I1Sl<strong>al</strong>l1<br />

1 east-pos 1 t 1 ve-doubl e-float COllsl<strong>al</strong>l1<br />

least-pos it ive-long-float<br />

COllsl<strong>al</strong>l1<br />

These have as their \'<strong>al</strong>ues the sm<strong>al</strong>lest numbers of the corresponding fonnats that can be<br />

represented. which are still positive.<br />

least-negative-short-float<br />

least-negative-single-float<br />

least-negative-double-float<br />

least-negative-long-float<br />

These have as their\'<strong>al</strong>ues<br />

corresponding fonnats.<br />

COIISlanl<br />

COllsl<strong>al</strong>l1<br />

COIlSltlnl<br />

COllsl<strong>al</strong>l1<br />

the most positive negati\'e numbers representable in the<br />

short-float-epsilon<br />

single-float-epsilon<br />

double-float-eps1l~n<br />

long-float-epsilon<br />

These have as their v<strong>al</strong>ues the sm<strong>al</strong>lest positive numbers which.<br />

corresponding fannat. produce a different answer.<br />

COI1Slanl<br />

COllsl<strong>al</strong>l1<br />

ConSlant<br />

COllslanl<br />

when added to 1.0 of thr<br />

short-float-negat1ve-eps11on<br />

single-float-negat1ve-eps11on<br />

dQuble~flo<strong>et</strong>-neg~t1ve-ep~1'on<br />

long-float-negative-eps11on<br />

These arc broKen and wrong.<br />

Constant<br />

('onstanl<br />

r_ .... _"' .........<br />

\,.. VIl.lIU'"<br />

COllslanl<br />

tvtC:<strong>NIL</strong>MAN:NUMBER 70<br />

23-DEC-83<br />

, , ~ ~ -<br />

. ,', . , :... .' :', . ';c ,-(: ',,: .> ,:;:~~~;;~~>',:-_: r~:'-, ":-, ....:;..:.


Characters 94 <strong>NIL</strong> Manu<strong>al</strong><br />

11. Characters<br />

In <strong>NIL</strong>. characters are represented as a separate data type. This provides multiple benefits;<br />

among them. the object maintains some semantic identity when it appears in code (it is obvious<br />

that it is a "character"). and since it does maintain its identity as a character. the read/print/read<br />

"fixed-point" is capable of functioning across differing LISP implementations that intern<strong>al</strong>ly utilize<br />

different character s<strong>et</strong>s (e.g.• ASC'II VS. EBCDIC).<br />

Characters in <strong>NIL</strong> have three different attributes: their code. their bils. and their [0111. 'Ibe<br />

code defines the basic ("root") chamcter. The bit"i are used as modifiers. Typic<strong>al</strong>1y. an input<br />

processor (such as the editor, or even the prescan for the tople\'c1 Lisp read-ev<strong>al</strong>-print loop) will<br />

treat a character without any bits as "ordinary" and assume it is part of the text being typed in.<br />

but treat a character with some bits, as being a command. Four of the speci<strong>al</strong> bits are named:<br />

they are control, m<strong>et</strong>a. super. and hyper. The font of the character defines how certain things<br />

about the character arc defined: for instance. equating characters of different fonts (char-equ<strong>al</strong>).<br />

wh<strong>et</strong>her a character is upper or lower case. <strong>al</strong>phab<strong>et</strong>ic. or a digit (upper-case-p <strong>et</strong>c.). and how<br />

to do case conversion (char-upcase). While NIl.' docs not y<strong>et</strong> rc<strong>al</strong>ly define "fonts", there is a<br />

mechanism for how such definitions can interface to the low-level character manipulation<br />

primitives which utilize such things (section 11.7. page 100).<br />

<strong>NIL</strong> character objects are immediate-pointer structures; they require no storage. Most of the<br />

routines which construct, dissect. and compare characters are open-coded by the compiler.<br />

Thc ~~lL character sct ha5 not y~t b~cn ck,iil~d up with respect tu -the cUllru~iulI UCLWCCIl Uu:<br />

ASCII control characters and the characters it uses with the control bit See section 11.6. page 99.<br />

char-code-l1m1 t<br />

Constant<br />

char-font-l1m1t<br />

Constant<br />

char-b1 ts-l1m1t<br />

Constant<br />

These variables have as their v<strong>al</strong>ues the upper exclusive limits on those attributes of<br />

characters. The v<strong>al</strong>ues should not be changed. It happens that, in the VAX<br />

implementation, <strong>al</strong>l three are 256 so that each quantity will fit into an g"bit byte.<br />

11.1 Predicates on Characters<br />

standard-char-p character<br />

This r<strong>et</strong>urns t if character is one of the "standard" ASCII characters. These are an the<br />

ordinary graphic characters (<strong>al</strong>phanumerics and punctuation characters). plus Space and<br />

R<strong>et</strong>urn. Only characters with 0 font and bits attributes can be standard.<br />

graph 1 c-char-p character<br />

R<strong>et</strong>urns t if character is a graphic (printing) character; that is. it has a single glyph<br />

representation. No character with non-zero bits attribute is graphic. Wh<strong>et</strong>her or not a<br />

character is graphic depends on its font<br />

MC:<strong>NIL</strong>MAN;CHAR 33


<strong>NIL</strong> Manu<strong>al</strong><br />

95 Predicates on Characters<br />

<strong>al</strong>pha-char-p character<br />

upper-case-p character<br />

lowe r - ca s e - p character<br />

both-case-p character<br />

a1 phanumer 1 cp character<br />

Predicates on character objects. All arc nil for characters with any bits; ()thcrwisc~<br />

depend on the font.<br />

thcy<br />

char- character &rest more-characters<br />

char( character &rest more-characters<br />

char(- character &rest more-characters<br />

char> character &rest more-characters<br />

ch a r> - character &rest more-characters<br />

charI- character &rest more-characters<br />

These routines collate or compare characters. The comparison is depcndent on the bits,<br />

fon4 and case of the characters. Each routine r<strong>et</strong>urns t if <strong>al</strong>l pairwise combinations of its<br />

arguments satisfy the appropriate predicate~ nil otherwise; if a single argument is givcn,<br />

the result is t.<br />

char = is the primitiv~ function for tclling if the characters are "thc same charactcr"-that<br />

is, if their code, bjts. and font arc <strong>al</strong>l the samc. It is what is used by eql and equ<strong>al</strong> for<br />

comparing characters. char / = r<strong>et</strong>urns. t if none of the pairs of characters are char = .<br />

ch~r =, =d cn:lr) cc!mtc t'1c eh~rnctcrs ~eeording to some unspecified<br />

collating sequence. What is guaranteed is that the upper-case<strong>al</strong>phab<strong>et</strong>ics, the lower-case<br />

<strong>al</strong>phab<strong>et</strong>ics, and the digits will not bc intcrspersed within thc coUating sequence, and,<br />

within each of these s<strong>et</strong>s, they follow the obvious coUating order.<br />

char-equ<strong>al</strong> character &rest more-characters<br />

char-l essp character &rest more-characters<br />

char-greaterp character &rest more-characters<br />

c h a r - no t -1 e ssp characler &rest mor~characters<br />

char-not-greaterp character &rest more-characters<br />

These routines compare characters independently of font, bits. and case. This does not<br />

mean that only the code portion of the characters is compared, but rather a fontdependent<br />

canonicaHzation is performed on the characters before they are compared.<br />

Thus, for two characters in different fonts, it is possible for them . to not be char-equ<strong>al</strong><br />

even if they have the same code (one might be a "greek" character and the other<br />

"roman"), and conversely it is possible for them to be the same even with different codes<br />

(one might be upper-case and the other lower-case).<br />

MC:<strong>NIL</strong>MAN;CHAR 33<br />

23-DEC-83


Ch4lmcter Construction and Selection 96 <strong>NIL</strong> Manu<strong>al</strong><br />

11.2 Character Construction and Selection<br />

character jrobozz<br />

Coerces jrobozz to a character. It may be a character. a fixnum. in which case char-int<br />

is applied. or a string. symbol. or character vector of length 1. in which case that single<br />

character is r<strong>et</strong>urned. This is what is used· by the coerce function (page 9).<br />

char-code character<br />

char-bits character<br />

char-font character<br />

These three functions extract those attributes (as fixnums).<br />

by the compiler. and accept only character objccts.<br />

AI) are efficiently open-coded<br />

code-char code &option<strong>al</strong> (bils 0) (font 0)<br />

Creates. a character with code, bits, and font of code. bils. and font. unless that is not<br />

possible in the implementation. in which case nil is r<strong>et</strong>urned. In other words. it is an<br />

error for code. bils. or fonl to not be. non-negative integers, however they need not be<br />

less than char-code-limit, char-bits-limit. and char-font-limit respectively.<br />

maKe-char char &option<strong>al</strong> (bitsO) (jontO)<br />

Creates a character with code of the the code of char. and with bits and font of bils and<br />

jont. unless that is not possible in the implementation, in which case nil is r<strong>et</strong>urned.<br />

make-char could have been defined as<br />

(dp.flln maIcA-r.har {t::"~r &option<strong>al</strong> (bits 0) (font 0»<br />

(code-char (char-code char) bits font»<br />

11.3 Character Conversions<br />

char-upcase char<br />

char-downcase char<br />

Upper- or Jower-casify char, preserving the font and bits attributes of it. Note in<br />

particular that these functions just r<strong>et</strong>urn char if it has a non-zero bits attribute, because<br />

such a character is not <strong>al</strong>phab<strong>et</strong>ic and hence not subject to having its case changed.<br />

char-i nt char<br />

R<strong>et</strong>urns a non-negative integer (in <strong>NIL</strong>. this will be a fixnum) encoding of the character<br />

char. If the bits and font of char are 0, this is the same as char-code. This is useful<br />

for hashing. and certain charactcr-fixnum conversions such as those needed for the<br />

MACLISP tyi function are defined in tenns of char-int.<br />

1nt-char integer<br />

If there is some character c for which (char-int c) equ<strong>al</strong>s integer, that character is<br />

r<strong>et</strong>urned; otherwise. nil is r<strong>et</strong>urned.<br />

~1C:NII.MAN:CHAR 33<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 97 Intern<strong>al</strong> Error Checking Routines<br />

char-name char<br />

R<strong>et</strong>urns the name of the character char, if it has one. Supposedly. <strong>al</strong>l characters which<br />

have zero font and bit4i attributes and which are non .. graphic (see graphic-char-p) have<br />

names.<br />

In <strong>NIL</strong>. the name of a character is by convention a symbol in the keyword package.<br />

name-char sym<br />

The argument S)'111 must be a symbol. If the symbol is the name of a character object.<br />

that object is r<strong>et</strong>urned: otherwise nil is r<strong>et</strong>urned.<br />

In !'II. character name symhols arc symbols in the keyword p4lCk~lge.<br />

d1git-char-p digit &oplion<strong>al</strong> (radix 10)<br />

digit-char-p is a semi-predicate. If digit, which must be a chanlcler, is a digit in radix<br />

radix. then the weight of thm digit is r<strong>et</strong>urned. otherwise nil is r<strong>et</strong>urned. By definition. a<br />

character with non-zero bits is not a digit. so for that digit-char-p will <strong>al</strong>ways r<strong>et</strong>urn nil.<br />

digit-char u'£'iglrl &optionaJ (radix 10) (fimf()<br />

I f it is possible to construct a chilracter with the given bits and font which has the weight<br />

weigh! in radix radix ~ then such a character isr<strong>et</strong>urncd. otherwise nil is rcturned. weight<br />

must be a \ <strong>al</strong>id weight for thc radix (a non-negativc integer less th,m radix). Note the<br />

similarity to make-char (page 96) <strong>al</strong>so.<br />

(digit-char 5) => #\5<br />

(digit-char 10) =~ nil<br />

(digit-char 10 25) => #\A<br />

Note that unlike make-char, digit-char does not take a bils argument. This is because<br />

a character with a non-lero bits attribute is by definition not a digit.<br />

11.4 Intern<strong>al</strong> Error Checking Routines<br />

The following may be of use to uscrs writing their own routines for dc<strong>al</strong>ing with characters.<br />

(They should eventu<strong>al</strong>ly be supplanted by more gener<strong>al</strong> type-checking macros, which will probably<br />

turn into c<strong>al</strong>ls to these routines ... )<br />

s1: requ1 re-character character<br />

Error.;checks that character is in fact a character. This is what is c<strong>al</strong>led by (for example)<br />

the interpr<strong>et</strong>ed version of char-code.<br />

s 1: requ1 re-character-f1xnum integer<br />

Error-checks that illteger is in fact an integer for which there is a character representation:<br />

that is, on whichint-char would r<strong>et</strong>urn a character. All such intcgers in <strong>NIL</strong> happen to<br />

be non-negative fixnums.<br />

MC:NII.MAN:CHAR 33<br />

23-DEC-83


I.ow-I.evel I nterf~lces 98 Nil. Manu<strong>al</strong><br />

11.5 LOl\'·Level Interfaces<br />

Xint-char fixllum<br />

Non-check version of jnt-char. It is an error for fixllum to not be the integer encoding<br />

of a v<strong>al</strong>id character object. as would be r<strong>et</strong>urned by char-int.<br />

The following four routines define digitness in the <strong>NIL</strong> character s<strong>et</strong>. at a low level. These<br />

routines do 1101 depend on the fillli of the character (if they take a character as an input); rather,<br />

they dcfine thc basic conversions for the "standard" ~IJ. character s<strong>et</strong> (~II"S interpr<strong>et</strong>ation of<br />

ASCII).<br />

% v a 11 d - dig 1 t - r ad 1 x - p radix<br />

This defincs the v<strong>al</strong>id rangc of radices which %digit;..char-in-radix opcratcs on. The<br />

radix must he a fixnum.<br />

%d1 g1 t-char-1 n - radix -p char radix<br />

Primili\'c predicatc for testing whcther thc charactcr ohject char is a digit character in the<br />

fixnum radix radix (which must be a v<strong>al</strong>id numeric radix).<br />

%digit-char-to-we1ght dwr<br />

For any char which satisfies %digit-char-in-radix-p, this will r<strong>et</strong>urn the weight of that<br />

digit.<br />

%d1g1t-we1ght-to-char weiRhl<br />

This inverts %digit-char-to-weight.<br />

The fonowing two routines perfonn low-level case mapping for the <strong>NIL</strong> character s<strong>et</strong><br />

%char-upcase-code code<br />

%char-downcase-code code<br />

These routines perform low-level case mapping for the <strong>NIL</strong> character s<strong>et</strong> code must be a<br />

v<strong>al</strong>id character code; the r<strong>et</strong>urned v<strong>al</strong>ue is a character with 0 bits and font attributes.<br />

For example. if <strong>NIL</strong> did not provide low-level support for multiple fonts,<br />

(char-equ<strong>al</strong> el e2)<br />

would be the same as<br />

(char= (%char-upcase-code (char-code el»<br />

(%char-upcase-code (char-code el»)<br />

The actu<strong>al</strong> definition of char-equ<strong>al</strong> is somewhat different in that the translation and<br />

canonic<strong>al</strong>ization of the characters depends on their font<br />

MC:NII.MAN:CBAR 33<br />

2J-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 99 The N II. Character S<strong>et</strong><br />

11.6 The NI L Character S<strong>et</strong><br />

As can be seen. the format of character objects in <strong>NIL</strong> provides for a basic eight-bit root<br />

charactcr (defined by the code). which can then have both bils and fOllt attributes added to it.<br />

However. the 1/0 devices l':ILmust de<strong>al</strong> with only handle (at most) eight-bit characters-often<br />

only scven.<br />

In principle, !\Il wilt utilize an eight-bit character s<strong>et</strong>; h<strong>al</strong>f of these witl be graphic characters<br />

(the norm<strong>al</strong> ASCII graphics. plus speci<strong>al</strong> symbols), and the other h<strong>al</strong>f reserved. foonat effectors<br />

(such as line feed. backspace), and speci<strong>al</strong> commands for things like the editor and debugger<br />

(Aborl. Resume. C/eor".\'cr{'cll. that kind uf tJ'ling). All oftJ'lcse chamc(ers will then he ahlc to<br />

have bils mld jiml <strong>al</strong>lribu(es added.<br />

To de<strong>al</strong> with tJlis on (for instance) an urdinary seven-bit ASCII tennin<strong>al</strong>. 'II will haye to do<br />

mrce thil)gs in the future. These are not done now. but are noted because they have bearing un<br />

me representation of character objects and input from devices.<br />

I Turn ordinary ASCII con£rol charilcters into the ~II \ersion of the control character. For<br />

instance. the :\sell character with code of 1. which is what you g<strong>et</strong> when typin~ ('amm/­<br />

A on a standard ASCII keyboard. will turn inw tJ1e character A (uppercase 1\) with the<br />

COlltrol bit s<strong>et</strong>.<br />

2 Provide "prefix" character-Je\"el commands in variolls places in order U14lt other chanlctcrs<br />

with bits may be entered (this is what is done in the editor). For instance. in the current<br />

inpl1f rnl('('~"()r t'4;


Primili\'e Fonl I }cfinitions 100 <strong>NIL</strong> Manu<strong>al</strong><br />

$ s<strong>et</strong> term/eightbit<br />

to (>Ct,.) Now we have a seven-bit character. If the seven-bit code is less than 32. and if it is not<br />

one of the codes for Backspace. Tab. Lill efeed. or R<strong>et</strong>urn (8. 9. 10. and 13 respective1y). then<br />

add 64 to it. and s<strong>et</strong> the {olllro/ bit. Adding 64 fonns the corresponding uppercase-<strong>al</strong>phab<strong>et</strong>ic or<br />

punctuation character. Thus. 1 turns into {o1llro/-A (65 plus Control). and 135 turns' into<br />

{vlllrv/-Afela-G (135 = 128 + 7. = A.Jela + CQllIro/ + 73 which is G).<br />

11.7 Primitive Font Definitions<br />

Thi\ section d<strong>et</strong>ails how "fonts" are described at a low level in \11, in order to be interfaced<br />

to the character primiti\'es described in this chapter. The contents of this section can he s,,'c1y<br />

ignored by anyone who isn't going to try to define fonts and interf~lce them to !':IL.<br />

first. remer:tber that the code portion of a character is exactly 8 bits.<br />

There are sever<strong>al</strong> ttattributes" of a font which we need to encode in such a way that certain<br />

operations become trh': <strong>al</strong>. They are these:<br />

C(}Il\'crsioll 10 Ul'l'Cl case<br />

('ol1\'crsieJl/ 10 !owe,..case<br />

These want to be done rapidly<br />

Icsling/or ('crlain <strong>al</strong>fribulcs<br />

the predicates upper-case'-p. graphic-char-p. both~case-p. <strong>et</strong>c.<br />

cOIllParison of charactcrs of d~(rere11l fOil IS<br />

Two go<strong>al</strong>s are desired here. It may be desirable for two characters in different fonts with<br />

the same code to 1101 be char-equ<strong>al</strong>. because they represent different things. It might<br />

<strong>al</strong>so be desirable for two characters in different fonts with different codes to be charequ<strong>al</strong>-one<br />

might be p. the other P.<br />

gelling H'ciglils of digits<br />

obtaining digit characters from weights<br />

For efficiency. <strong>al</strong>l of these go<strong>al</strong>s are implemented through table lookup. There are sever<strong>al</strong><br />

speci<strong>al</strong> variables whose v<strong>al</strong>ues are simple vectors which contain one entry for each possible font<br />

(256 entries in each vector). In the initi<strong>al</strong> <strong>NIL</strong> environment. <strong>al</strong>l of the entries of each vector are<br />

initi<strong>al</strong>ized to the same thing.·<br />

Before these tables g<strong>et</strong> listed, there are a couple of conventions which must be explained first<br />

The first is what is caned intern<strong>al</strong>ly a translation table for characters. 1bis is just a simple-string<br />

or simple-bit-vector 256 bytes (2048 bits) )ong~ for doing code-to-code translation. For instance,<br />

translation to upper-case for a particular font utilizes such a table. The <strong>NIL</strong> primitives are defined<br />

such that it docs not matter wh<strong>et</strong>her this datastructure is a simple-bit-vector or a simple-string.<br />

Another such datastructure is a sy1l1ax table. This is the same as a translation ciblc~ but each<br />

byte within the table is treated instead as a bit-mask with one bit s<strong>et</strong> for each attribute about the<br />

code being defined. Both of these concepts will be abstracted away from characters in a' future<br />

~JL<br />

1be attributes about a font we define arc these:<br />

uppr,..casc IransT<strong>al</strong>ion lable<br />

lowe,.case tr<strong>al</strong>lsl<strong>al</strong>ioll/able<br />

MC:NlI.MAN:CHAR 33<br />

23-DEC-83<br />

" .<br />

, . _', _ -. -' , .' • ~ c " ' ~ - , • '," - ,


<strong>NIL</strong> Manu<strong>al</strong> 101 Primitivc Font Definitions<br />

Etch font has one of each of these. ehar-upease works by r<strong>et</strong>urning a new character of<br />

the same font. with a code which is the result of extracting the byte from the upper-case<br />

translation table at the code index. (If the character has non-zero bits it is just r<strong>et</strong>urned<br />

however.)<br />

syntax table<br />

A syntax table (as described above) with syntax bits for the character primitives graphieehar-p.<br />

upper-ease-po lower-ease-p. both-ease-po <strong>al</strong>phanumeriep. and <strong>al</strong>phaehar-p.<br />

Constants for these bits are defined below.<br />

digit weight table<br />

This is a simple vector 256 long with one entry for each character code. All entries are<br />

fixnul11s. Those entries corresponding. to characters which cannot ever he interpr<strong>et</strong>ed as<br />

digits should he -1: <strong>al</strong>l others should have the weight of the digit.<br />

digil cliar lable .<br />

This is a simple-string (it must 1101 be a simple-bit-vector) used for conversion from a digit<br />

. weight to thc corresponding character. The length of the string is the maximum radix<br />

which 'can be handled in that font. and <strong>al</strong>l entries in-b<strong>et</strong>ween must be v<strong>al</strong>id. For<br />

iT: tance. in the standard such table. the entry at index 9 is the character 9. and the<br />

entry at index 12 is the character C.<br />

the 1)]J('Jilce<br />

The fonnat of this object is not defined: the typefaces of different fonts are compared<br />

with eq by such predicates as char-equ<strong>al</strong>. This is discussed later.<br />

Iypeface cGl1ol1ic<strong>al</strong>izatiolltable<br />

This is a simp]e vector 256 long. which is used to produce a canonic<strong>al</strong>il.ation of a<br />

character within a typeface. The eiemenlli ot the vector are tlxllurns. When two characters<br />

of the same typeface are compared. the code of each character is used as an index into<br />

this table (there is one per font. remember), and that result is used for the comparison.<br />

This <strong>al</strong>lows a typeface to have. among sever<strong>al</strong> fonts. more than 256 characters.<br />

s 1: nata-pr 1m1 t 1 va-fan t font-number &key upper-ease-translations syl1lax-table<br />

lower-case-translations typeface backwards-reference digit-weight-table<br />

digi I-chaT'" table t),peface-c<strong>al</strong>lonic<strong>al</strong>ization<br />

This assigns <strong>al</strong>l of the infonnation described above to the font fOllt-number. Appropriate<br />

defaults are assigned for those entries which are nil.<br />

The following constants define syntax bits used in the syntax table used. For each, the uSv_tt<br />

constant has as its v<strong>al</strong>ue the position of the bit within the field (byte), and the "Sm_tt constant a<br />

mask for testing the bit (with logtest&~ for instance) or s<strong>et</strong>ting it (with logior&).<br />

s1: charsyntax$v_graph1c Constant<br />

s 1: charsyntax$m_graph 1 c<br />

Constant<br />

This hit tells if the character is graphic; that is. if it should satisfy graphie-char-p.<br />

s1: charsyntax$v_uppar _case Conslant<br />

S 1: charsyntax$m_upper _case<br />

Constanl<br />

This bit tells if the character is upper case (should satisfy upper-case-p).<br />

MC:<strong>NIL</strong>MAN:CHAR 33<br />

23-DEC-83


Primitive Fonl Definitions<br />

102<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

s1:charsyntax$v_lower_case<br />

s1:charsyntax$m_lower_case<br />

This tells if the character is lower case.<br />

{OIlSlant<br />

ConSl<strong>al</strong>lt<br />

s1:charsyntax$v_both_caS8<br />

s1:charsyntax$m_both_case .<br />

This tells if the character satisfies both-case-p (page 95).<br />

s1:charsyntax$v_d1g1t<br />

s1:char5yntax$m_d1g1t<br />

This teBs if the chamcter is Cl (decim<strong>al</strong>) digit chamcter.<br />

COllstanl<br />

Constant<br />

COllslOllt<br />

COils/<strong>al</strong>ii<br />

s1 : charsyntax$v_standard<br />

('011.';/(1111<br />

51: charsyntax$m_standard COIiSIGllt<br />

This lells if thc character, were it if font O. is a s~1ndard char (standard-char-p. page<br />

94).<br />

s1: charsyntax$v_<strong>al</strong>pba COllsttlnt<br />

51: charsyntax$m_<strong>al</strong>pba COllsl<strong>al</strong>l1<br />

This tells if the chamcter is <strong>al</strong>phab<strong>et</strong>ic. If the chiJracter is either upper or lowef case.<br />

then it must have this bit s<strong>et</strong> <strong>al</strong>so. It is hypothctic<strong>al</strong>ly possihle. however. for a character<br />

to be <strong>al</strong>phab<strong>et</strong>ic but neither upper Of lower case.<br />

Character comparison <strong>al</strong>a char-equ<strong>al</strong>. char~lessp. <strong>et</strong>c .. i~performed itS follows. w~ :lSSllme<br />

thJt it is possible to group characters into logic<strong>al</strong> "typefaces": canonic<strong>al</strong>il.ations within a typefllce<br />

are v<strong>al</strong>id. and comparisons of characters of different typefaces are not. Each font has associated<br />

with it one such typeface. and the assumption. is that many different fonts map to just a few<br />

typefaces. When two characters are compared. if their typefaces are the same. then the codes of<br />

the characters are translated into fixnums by obtaining the eod<strong>et</strong>h clements of the typeface<br />

canonic<strong>al</strong>ization tables, and the results compared in the appropriate manner (= for char-equ<strong>al</strong>, <<br />

for char-Iessp, <strong>et</strong>c.). If the typefaces arc ·different. then the characters are not equ<strong>al</strong>; for<br />

ordering, they are compared in a manner consistent with char


<strong>NIL</strong> Manu<strong>al</strong> 103 !\ITays<br />

12. Arrays<br />

Arrays in I'll _ encompass a large number of varied objects which share certain features and<br />

aspects of usage. <strong>NIL</strong> arrays may range in rank (number of dimensions) from 0 to about 250. All<br />

array indices in <strong>NIL</strong> are zero origined. One-dimension<strong>al</strong> arrays are veClors. are of the type vector,<br />

and may be used by the various sequence functions (in chapter 7). Restrictions on the types of<br />

the clements of an array (its elemenl IJpe) can result in speci<strong>al</strong> storage and access strategies. The<br />

data in multidimension<strong>al</strong> arrays is <strong>al</strong>ways stored in row-major order; this is compatible with<br />

MACI.ISP. <strong>al</strong>though nonn<strong>al</strong>ly it docs not matter-.<br />

12.1 Array Creation,! Access,! and Attributes<br />

make - ar r 8y dimcllsilills &key el(,1I1(,III-I)1)C displaced-Io displa('('d-ind('x-ojfs('/ <strong>al</strong>fius/able<br />

jill-poil1lcr<br />

This is the gener<strong>al</strong> array creation function. dimensions may be an integer. in which case<br />

the rank of the created array will he_ one (it will he a vector). or a list of integers which<br />

are the sizes of the correspondhq dimensions of the array.<br />

The array wi11 be created to hold objects of type ('/('melll-I)1)C. If this is not supplied. t is<br />

assumed. and the created array will be able to hold any lisp objects. The most common<br />

types. aside from t. are bit (which creates a bit-array). and string-char (which creates a<br />

string-char-array). The speci<strong>al</strong> types which Jl'IL supports. and their consequences. arc<br />

tii~"lIcc(\ti ..........-.-..,.......- ............ in c",.,inn _....".... 1"" "--;-4 "''tnt> 11\.1<br />

.t'~C" .&.v ••<br />

If jill-poilller is not null. then the array must be one-dimension<strong>al</strong> (a vector). It will be<br />

created with a fill pointer initi<strong>al</strong>ized to jill-pointer. which must be b<strong>et</strong>ween zero and the<br />

size of the array (inclusive). Fill pointers arc discussed in section 12.3. page 105.<br />

Nonn<strong>al</strong>ly, the size of an array may not be changed (other than by modification of its fill<br />

pointer if it has one). This <strong>al</strong>lows the implementation some leeway to provide for more<br />

efficient access and storage. However, if adjustable is specified and not nil, then the array<br />

will be created in such a way that its size (and its displacement attributes) can be<br />

modified later by adjust-array. Modification of array size and attributes is discussed in<br />

section 12.5. page 107.<br />

The displaced-to and displaced-index-offs<strong>et</strong> arguments control array displacement; that is<br />

where one array can "point into" another. This is discussed in section 12.4. page 107.<br />

are' array &rest indices<br />

R<strong>et</strong>urns the element of array addressed by the indices. The number of indices must<br />

match the rank of the array, and each index must lie b<strong>et</strong>ween zero (inclusive) and the<br />

size of the corresponding dimension of the array (exclusive).<br />

If the array is one dimension<strong>al</strong> (Le .• a vector) and has a fin pointer. the fill pointer is 110t<br />

used to decide the range of the array which may be v<strong>al</strong>idly referenced: aref may be used<br />

to access <strong>al</strong>l clements of such an array. In this, it differs from elt (page 49).<br />

MC:<strong>NIL</strong>MAN;ARRAY 36<br />

23-I)FC-83


Array Element Types 104 <strong>NIL</strong> Manu


-------------------------------<br />

<strong>NIL</strong> Manu<strong>al</strong> 105 FiJI Pointers<br />

string-char<br />

The array can only hold characters which satisfy the predicate string-char-p (page 19).<br />

A one-dimension<strong>al</strong> array of this clement-type is of type string. A string that is not<br />

adjustable, not displaced, and has no fin pointer is of the type simple-string: this is<br />

implemented more efficiently than a more gener<strong>al</strong> string~ and can be efficiently accessed<br />

with the schar function (page 114). Chapter 13 is devoted to strings.<br />

character<br />

The array can hold only characters (but they may be any type of characters). This<br />

provides no advantage over the clement-type t in the current implementation: in a later<br />

'II., vectors of clement-type character will he acceptahle to the string function~ (chapter<br />

13).<br />

(unsigned-byte 8)<br />

(signed-byte 8)<br />

(unsigned-byte 16)<br />

(signed-byte 16)<br />

Store those integers which arc representable in tl··~<br />

respective fields.<br />

double-float<br />

The double-floats arc stored p,lCked in machine representation. Until lhe' compiler has<br />

sufficient power to speciaJly handle accesses to arrays of this type, there is no particular<br />

benefit to their usc. because a generic array reference to a dl.luhle-float array will have to<br />

cons the number to r<strong>et</strong>urn it.<br />

t Au aIT"y \if dement-type t ean h\ild any lisp (}bjc~t. If sli~h dB eli"d), i~ um:-Jilm:lJ~iullai.<br />

not adjustable. not displaced. and has no fill pointer. then it is a simple vector (of the<br />

type simple-vector). Such a vector is especi<strong>al</strong>ly efficient, and may be accessed with the<br />

svref function (page 109).<br />

12.3 Fin Pointers<br />

The :fill-pointer option to make-array <strong>al</strong>lows one to create a vector of varying length. It is<br />

only applicable to one-dimension<strong>al</strong> arrays. The fill pointer of a vector is an integer which may<br />

range from 0 to the size of the vector. 1t is used as the length of the vector; the v<strong>al</strong>ue of the fill<br />

pointer will be r<strong>et</strong>urned by length (page 49). and used as the length by <strong>al</strong>l sequence and string<br />

functions: in fact, by everything except for aref (and its variants such as char and bit). The<br />

contents of the array at and beyond the fill pointer are still considered v<strong>al</strong>id;· they just are not<br />

considered when the array is viewed as a sequence.<br />

A string with a fill pointer is reputed to be similar to a PL/I varying string. <strong>al</strong>though such a<br />

comparison is beyond the re<strong>al</strong>m of this author's knowledge.<br />

To find the actu<strong>al</strong> <strong>al</strong>located length of a vector which has a fill pointer, use array-dimension<br />

with a dimension number of O. array-dimension <strong>al</strong>ways r<strong>et</strong>urns the <strong>al</strong>10catcd length.<br />

f\·1C:NII.MAN:ARRA Y 36<br />

23-DEC-83<br />

... - ~...


Fill Pointers 106 <strong>NIL</strong> Manu<strong>al</strong><br />

array-has-f111-pofnter-p array<br />

This r<strong>et</strong>urns t jf array has a fill pointer (implying that it is a vector). nil otherwise. It is<br />

an error for array to not be an array.<br />

fill-poi ntar vector<br />

This r<strong>et</strong>urns the fill pointer of vector, which must bea vector with a fill pointer. " lnis<br />

may be used with s<strong>et</strong>f.<br />

vector-push \JeClor object<br />

reClor must be a vector with a fiU pointer. If the fiU pointer is a vaJid index into the<br />

\ector (that is. its \".llue is J~ss than the <strong>al</strong>located length of the ,"ector). then vector-push<br />

SlOres (}/~i('('1 into thilt slot. incr~l1lents the fill poi Iller. .md re(Urns the origin<strong>al</strong><br />

(linincremented) fill pointer (which address~s where the uhject was stored). If the filt<br />

pointer is the same as the <strong>al</strong>loc<strong>al</strong>ed length (the only other v<strong>al</strong>id situation). then vectorpush<br />

r<strong>et</strong>urns nil.<br />

Note that the argument order to vector-push differs from that of the push macro (page<br />

38). This will be incompatibly chmlged in the future. at which time ver.tor-push will<br />

contrive to figure out which argument is which from their types.<br />

vector-push-extand vector object &option<strong>al</strong> extension<br />

This is like vector-push. but whereas vector-push will r<strong>et</strong>urn nil if the vector is "fun",<br />

vector-push-extend will instead can adjust-array to incre,lse the si7e of V('Clor in order<br />

thilt if miehr no the:- pnli;h. Thu~, it nl?\'l~~ rt:tt!r!l~ niL If ~X{!>f?!f(lf? is 5upp1i{'d and not nU.<br />

then that is the amount by which the size of \'eclor is incremented by adjust~array, if<br />

necessary; otherwise. some random guess based on the current sizcis used.<br />

In order for adjust-array to succeed in increasing the size of veclor. l'l'clor must have<br />

been cre<strong>al</strong>ed with the :adjustable option to make-array; see section 12.5, page 107.<br />

The ordering of the arguments vector and object will be reversed in the future; see<br />

vector-push, above.<br />

vector-pop vector<br />

This is the inverse of vee/or-push. The fill pointer of vector is decremented, and the<br />

object addressed by that index is r<strong>et</strong>urned. The fill pointer must not <strong>al</strong>ready be zero.<br />

res<strong>et</strong>-fill-pointer vector &option<strong>al</strong> (illdexO)<br />

Res<strong>et</strong>s the fin pointer of veclor, which must have one. If index is not specified, 0 is<br />

assumed.<br />

This function is obsol<strong>et</strong>ed by the use of fiU"pointer with s<strong>et</strong>f.<br />

One common use of vectors with fill pointers is as buffeTS. For example. the <strong>NIL</strong> compiler<br />

lIses a vector with a fin pointer for anocating a tahle of v<strong>al</strong>ue cell indices to be referenced by the<br />

code it is compiling. It creates a vector with make-array. specifying that the array is adjustable,<br />

mld gi\ ing it an initi<strong>al</strong> fill pointer of O. Then. it uses vector-push-extend to add Cl new entry,<br />

and the v<strong>al</strong>ue thm r<strong>et</strong>urns is the index into this table. vector-push -extend takes care of<br />

increasing the size of the vector jf the initi<strong>al</strong> guess as to its size was too sm<strong>al</strong>l.<br />

MC~NII.M;\N:ARRAY 36


N II. Manu<strong>al</strong> 107 Displaced Arrays<br />

This same technique can be used for generating text. jf the vector is a string (that is. makearray<br />

was given string-char as the :element-type keyword). This is how some string<br />

accumulating primitives work.<br />

With vector-pop, vectors with fill pointers can <strong>al</strong>so be used as stacks.<br />

12.4 Displaced Arrays<br />

Arrays may be created which do not have data of their own. but in fact "share" data with<br />

some other array. These arc displacrt/ arrays. The lIses for displaced arrays \·<strong>al</strong>'}'. One might<br />

want to access the clements of a multi-dimension<strong>al</strong> array as if it were a \ ector: this could he<br />

done by<br />

(make-array size :displaced-to other-array)<br />

which r<strong>et</strong>urns a vector which will "ccess the clements of Oilier-array in row-major-order. With<br />

displacement. a displaced index offs<strong>et</strong> may <strong>al</strong>so be specified. Conceptu<strong>al</strong>ly, when an array is<br />

accessed. a single index is computed from the indices and dimensions of the array: this is the<br />

index into the row-major-order data. This iildex then has the displaced-index-offs<strong>et</strong> added to it.<br />

to gel the index into the data for the array being displaced to.<br />

Another potenti<strong>al</strong> use for displaced arrays is to reference some "substructure" of an array<br />

which implicitly has some ·'structure". This causes modification of the displaced array to modify<br />

the referenced subpart of the origin<strong>al</strong> array. In genera1. however. it is not appropriate to use<br />

array displacement as a substitute for a subseq operation (page 50): it is intended fi1f cases<br />

where modification of one must implicitly nl0dify the other. <strong>al</strong>though if the subsequence is large<br />

it may be worthwhile.<br />

Efficiency note; displaced arrays which are displaced to non-adjustable arrays access at just<br />

about the same speed as nonn<strong>al</strong> arrays (not counting those which are especi<strong>al</strong>ly efficient. namely<br />

simple vectors, simple strings, and simple bit vectors). Arrays displaced to adjustable arrays are a<br />

touch slower. At this time. the l':IL compiler does not know how to inline code any non-vector<br />

array access, however, so aref (or use of it with s<strong>et</strong>f) will produce gener<strong>al</strong> function c<strong>al</strong>l unless<br />

there is exactly one index.<br />

12.5 Modifying Array Sizes and Characteristics<br />

Nonn<strong>al</strong>ly, an array may not have the size of its dimensions or other attributes changed once<br />

it is created (other than modification of its fill pointer; section 12.3, page 105). If a non-null<br />

:adjustable option is given to make-array, however, the array will be created such that this is<br />

possible.<br />

·adjust-array array dimensions &key displaced-to displaced-index-offs<strong>et</strong> element-type<br />

jill-pointer<br />

adjust-array interpr<strong>et</strong>s dimellsio11s just as make-array docs. The array is modified to<br />

have the new dimensions; however. its rank may not be changed.<br />

If jill-pointer is specified. then array must have origin<strong>al</strong>ly been created with a fill pointer:<br />

the v<strong>al</strong>ue of ftll-poilller is used as the new one.<br />

MC:NII MAN:ARRAY 36


..<br />

Speci<strong>al</strong> Vectur Primitives 108 Nil. Manu<strong>al</strong><br />

The remaining options wi11 not be d<strong>et</strong>ailed at this time. adjust-array currently only<br />

works on one-dimension<strong>al</strong> arrays. so <strong>al</strong>though not gener<strong>al</strong>ly useful y<strong>et</strong>. it has enough to<br />

keep vector-push-extend happy.<br />

12.6 Speci<strong>al</strong> Vector Primitives<br />

These functions arc around in <strong>NIL</strong> for historic<strong>al</strong> reasons. They should gener<strong>al</strong>1y not be used<br />

in new code. for reasons which will become clear from reading the descriptions. They arc<br />

documented because they arc used aU over the place in Nil. itself still. and vref in particular is<br />

generated intern<strong>al</strong> hy the compiler from the usc of aref.<br />

vref }'('('lOr index<br />

'111is is absolu(('(J' idflllic<strong>al</strong> to aref when aref is given a vector and a single index. ar<strong>et</strong> is<br />

tJle preferred function to usc in code~ the <strong>NIL</strong> compiler compiles aref· of it single index as<br />

a c<strong>al</strong>l to this intern<strong>al</strong> vector-referencing subroutine.<br />

Because this is the same as aref on a one-dimension<strong>al</strong> array. It IS Ultcresting to note tJlat<br />

(for a vector with a fill pointer) vref does not usc the vector-length to check if the index<br />

is in range.<br />

vector-l ength vector<br />

For historic<strong>al</strong> reasons, this is the same as length but only accepts a vector as an<br />

argument. If the vcctor has a fin pointer. this is not the same as (array-dimension<br />

l'ector 0). which is the quantity used by vref for boundscheckjng.<br />

12.7 Simple Vectors<br />

Vectors of elcment-type t which are not adjustable and have no fill pointer are implemented<br />

as the primitive data type simple-vector. (This was c<strong>al</strong>led simple-gener<strong>al</strong>-vector in the<br />

'previous <strong>NIL</strong> release. Do 1101 misinterpr<strong>et</strong> the name. simple-vector to mean one encompassing<br />

vectors of other clement types.) This type is extensively used in <strong>NIL</strong> as a building block for more<br />

complicated datastructurcs in <strong>NIL</strong>. including less· simple arrays. There arc speci<strong>al</strong> routines for<br />

creating and manipulating them, which are coded cfficiently by the <strong>NIL</strong> compiler.<br />

Vectors of this type may be checked for with typep, of course.<br />

lIlake-vector size &key initi<strong>al</strong>-contellts initi<strong>al</strong>-element<br />

Makes a vector of element-type t. size long. Because no complicated array options can be<br />

specified, this will <strong>al</strong>ways be a simple vector.<br />

This may be caned make-simple-vector in the future, but the name make-vector will<br />

be preserved indefinitely.<br />

MC:NII.MAN:ARRA Y 36


pa<br />

<strong>NIL</strong> Manu<strong>al</strong> 109<br />

Bit Arrays<br />

vector &rcst elemellls<br />

This makes a simple vector whose clements are initi<strong>al</strong>ized to elements. That is.<br />

(vector 123) => #(123)<br />

svref simple-vee/or index<br />

<strong>Reference</strong>s a simple vector. This routine, is entirely open-coded by the compiler, with no<br />

error checking; to r<strong>et</strong>ain nmtime type and bounds checking. aref must be used.<br />

svref may be used with s<strong>et</strong>f.<br />

This function used to be c<strong>al</strong>led sgvref: th41t name is still around.<br />

simple-vector-length vcelvr<br />

. R<strong>et</strong>urns the length of the simple vector "ector.<br />

, This used to be c,.1Jed simpJe-gener<strong>al</strong>-vector-length (yow!): that name is still around.<br />

12.8 Bit Arrays<br />

Arrays which contain only bits. which can be used to represent boolean true and f<strong>al</strong>se, are<br />

useful in various applications. There arc sever<strong>al</strong> functions which perform boolean operations on<br />

arrays of this clement type.<br />

Bit arrays may be more or iess appropnate ior a panlcuiar apphcatlon than integers used to<br />

represent a sequence of bits. Bit arrays (or bit-vectors) may be side-effected: integers may not.<br />

Integers however may be used to represent infinite s<strong>et</strong>s. because they are vinu<strong>al</strong>ly extended with<br />

their sign: see <strong>al</strong>so section 10.S. page Sl. Bit arrays, of course, may be multi-dimension<strong>al</strong>.<br />

bit bit-array &rest subscripts<br />

Just like aref (page 103), but only works on arrays of clement-type bit.<br />

s<strong>et</strong>f may be used with bit.<br />

s b 1 t bit-array &rcst subscripts<br />

This is just like bit, but is only for use on simple bit arrays. This can result in much<br />

more efficient code, especi<strong>al</strong>ly if the bit-array is one-dimension<strong>al</strong>.<br />

s<strong>et</strong>f may be used with sbit.<br />

b 1 t - an d bit-array-] bit-array ..] &option<strong>al</strong> resu/t-bit"orroy<br />

bit-ior bit-array-] bit-array-] &option<strong>al</strong> result-bit-array<br />

b 1 t - xo r bit-array-] bit-array ..] &option<strong>al</strong> result-bit-array<br />

b1 t-eqv bit-array-] bit-array-] &option<strong>al</strong> resu/t-bit-array<br />

bit-nand bit-array-l bit-array-] &optionaJ result-bit-orray<br />

bit-nor bit-array-i bit-arra"v-] &option<strong>al</strong> result-bit-array<br />

bit-andc1 bil-arrl1y-i bil-array-2 &option<strong>al</strong> result-bit-array<br />

bit-andeZ bit-array-I bit-array-] &option<strong>al</strong> result-bit-array<br />

bit-orc1 bit-arruy-i bil-array-l &option<strong>al</strong> resull-bil-array<br />

bit-orcZ bit-array-l bil-array~] &option<strong>al</strong> result-bit-array<br />

MC:NII.MAN:ARRA Y 36<br />

23-DEC-83


Hit Arrays 110<br />

These cnmch tog<strong>et</strong>her bit-array-/ and bi/-arm)'" 2. pcrfonning the appropriate bitwise<br />

logic<strong>al</strong> operation. bi/-urray-} and bit-array"} must have the same rank and dimensions. If<br />

result-bit-array is nil or not specified. then the . result is a freshly created bit array of the<br />

same rank and dimensions. If it is t. then the resuJlc; are stored in bit-orrar I.<br />

Otherwise. it must be a bit array of the same rank and dimensions as the other two, and<br />

the results are stored intO it<br />

b 1 t - no t hi/-array &optionaJ r{'sult-hit-aml)'<br />

Perfonns a bitwise logic~l1 negation on the contents of bit-array. If rrsull-bil-arroyis nil or<br />

nOl specified. then the result is r<strong>et</strong>urned as a freshly created bit array of the same rank<br />

and dimensions as bit-array. If rrsu"-bil-a,.rt~l' is t. then hi/-array is side-effected with the<br />

n~~lIlts. Otherwise. ,.csul,-bihlrmy should be the a hit array of the same ranK ~md<br />

dimensions as bit-arr(l),. undwiU h<strong>al</strong>e the results stored into it.<br />

12.8.1 Simple Bit Vectors<br />

In '". a one-dimensiona1 hit array which is 'not adjus~lblc. nOl dispJaccd~ and has no fin<br />

pointcr. hi represented as the primithe t~ pesimple-bit-vector. which is reprcsented more<br />

efficiently than a more gener<strong>al</strong> bit array_ Simple bit vecturs are used as building blocks fur more<br />

complicated stmctures which contain binary data. such as the more complicated bit arrays. and<br />

even arrays of clement-type double-float. There are primitives for accessing variable length fields<br />

from them as (possibly sign-extended) fixnums. (but lIo/gener<strong>al</strong> integers. y<strong>et</strong>). and primitives for<br />

treating them il~ jf th~y w~r~ ~('qllen("~ of f'ight·hjrhyt~<br />

Once upon a time the name for this type was bits. This name still lingers in places. but is :<br />

heing replaced by simple-bit-vector.<br />

maKe-b1t-v8ctor size &key illiti<strong>al</strong>-element initi<strong>al</strong>-contents<br />

. Creatcs a simple-bit-vector size long. If neither initia/-element nor initia/-colltents are<br />

specified, the contents of the created bit-vector are undefined. 'The current implementation<br />

of l'IL storage <strong>al</strong>location requires that <strong>al</strong>l <strong>al</strong>located. datastructure be initi<strong>al</strong>ized, so in fact<br />

the bit-vector will <strong>al</strong>ways be initi<strong>al</strong>ized to zeros. but this could change in the future.<br />

If illiti<strong>al</strong>-elemelll is specified, it must be either 0 or 1. and the elements of the bit vector<br />

are initi<strong>al</strong>ized tothaL<br />

If initi<strong>al</strong>-contents is specified. then it should be a bit vector, and the created bit vector is<br />

initi<strong>al</strong>ized to the contents of illilia/-colltell/S. If initi<strong>al</strong>-colltellls is longer than size. the<br />

extra elements arc ignored: jf it is shaner, then the contents of the remaining elcmentsof<br />

the created bit vector arc undefined (just as they arc if neither :initi<strong>al</strong>"'element nor<br />

:initia1-contents are specified). It is an error to specify both illili<strong>al</strong>-elemtIl1I and initi<strong>al</strong>coiuenls.<br />

s1mple-b1t-vector .. length simple-hit-vPClor<br />

R<strong>et</strong>urns the length of simp/l""bit-ver;lor.<br />

MC:NII.MA'N:ARRAY 36<br />

23-DEC-83<br />

. ~ ..... ~ ~"<br />

~ .... ". '" .. ~ "'~ " ~ ,. r


•<br />

Nil. Manu<strong>al</strong> 111 Bit Arrays<br />

n 1 bb 1 e simple-bit-vector skip take<br />

R<strong>et</strong>unls the sequence of bits take long from simple-bit-vector. starting at skip. as a<br />

fixnum. take may range from zero to the number of bit~ representable in a fixnum (30)~<br />

however. if the last. the result will include the sign bit so may be unacceptable for<br />

certain applications. The result is zero-extended.<br />

s<strong>et</strong>f may be used with nibble to replace the field.<br />

n1bble-2c simplc-bit-veClOr skip lake<br />

l.ike nibble. hut the result is sign-extended. 'lbat is •. the result is interpr<strong>et</strong>ed as a signed<br />

hinary v<strong>al</strong>ue from the referenced field.<br />

s<strong>et</strong>f may he used with nibble-2c to replace the field.<br />

g<strong>et</strong>-a-byte simple-bit-vector byte-index<br />

Interpr<strong>et</strong>s simple-hit-vector as a sequence of type (unsigned -byte 8). and r<strong>et</strong>urns the byteindex<br />

th byte.<br />

s<strong>et</strong>f may he used with g<strong>et</strong>-a-byte.<br />

g<strong>et</strong> - a - byte-2c simple-bit-vector byte-index<br />

Interpr<strong>et</strong>s simple-bit-vector as a sequence of type (signed-byte 8). and r<strong>et</strong>urns the b)'/eindexth<br />

byte.<br />

s<strong>et</strong>f may be used with g<strong>et</strong>-a-byte-2c.<br />

\1C:NlI.MAN:ARRA Y 36


Strings 112 Nil. Manu<strong>al</strong><br />

. ]3. Strings<br />

Strings arc vcctors of characters which satisfy the prcdicate string-char-p(page 19).<br />

Although thc gcncric sequence and· array primitives operate on strings, there are two reasons for<br />

having addition<strong>al</strong> functions for strings. For Olle. it is convenient for atomic symbols to be used in<br />

pJace of strjngs~ symbols are not coerced to strings by sequence functions. but they are for most<br />

of the string functions. Additiona1Jy. many of the string functions which compare characters do so<br />

independcnt of the character case: the sequence functions are gener<strong>al</strong>ly based on thceql predicate<br />

(page 20). so are case dependent.<br />

FH'nlUaJly. the string functions will he gener<strong>al</strong>ized to handle arguments which are gener<strong>al</strong><br />

c.:h~tfa


.' ~;,<br />

<strong>NIL</strong> Manu<strong>al</strong> 113 String Comparison<br />

13.2 String Comparison<br />

When routines de<strong>al</strong> with boundaries within strings. there are two different conventions<br />

applied. Many functions take range arguments as the lower inclusive bound and the upper<br />

exclusive bound (gener<strong>al</strong>ly named start and end). These arguments conveniently default to 0 .and<br />

the length of the string (typic<strong>al</strong>ly). As a gener<strong>al</strong> rule. an upper exclusive bound may be explicitly<br />

specified as nil producing behavior as if it were mit specified; this is often necessary in order for<br />

following option<strong>al</strong> arguments to be spccified.<br />

The other commonty used substring convention is for a starting index and a count (gener<strong>al</strong>ly<br />

named start and ('OUllt) to be specified. (This convention is used primarily hy subprimithes. and<br />

old 'II functions. not (,0\1\10' LISP functions.) The suhstring in qucstion is that starling at the<br />

index. and proceeding for count characters. Hadng a specified count fun off the string is an<br />

error, and an explicit specification of a count of nil is not <strong>al</strong>lowed. Just about <strong>al</strong>l of the routines<br />

which s,til1 follow this subsequence convention are low-level 1'11. functions. in which the count is a<br />

required argument. so the question of how it defaults if not specified should not arise any more.<br />

Routincs using this convention som<strong>et</strong>imes n;lme these arguments skip and take rather than start<br />

and COUllt.<br />

string-equ<strong>al</strong> string! siring] &key (starl! 0) (sttlrt20) end! end2<br />

This r<strong>et</strong>urns t if the subsequence of sIring! from startl (inclusive) to end! (exclusive) is<br />

equ<strong>al</strong> (using case-independent character comparison. <strong>al</strong>a char-equ<strong>al</strong> (page 95» to the<br />

subsequence of string] from starf2 (inclusive) to end] (exclusive). The subsequences are<br />

St!~r~!!tccd to he uncqu:1! if t.."c ~!.!b$cqucncc lengths differ.<br />

As a speci<strong>al</strong> upwards-compatibility hack,<br />

arguments instead of keyword arguments.<br />

string-equ<strong>al</strong> will accept option<strong>al</strong> position<br />

string-nat-equ<strong>al</strong> stringl string2 &key (startIO) (start20) end/ end2<br />

The opposite of string-equ<strong>al</strong>. Similarly. the subsequences are guaranteed unequ<strong>al</strong> if their<br />

lengths differ.<br />

str1 ng-lessp stringl string2 &key (startl 0) (start20) end! endl<br />

str1ng-not-lessp string 1 string2 &key (starIIO) (slarI20) end! end2<br />

str1 ng-greaterp string! string2 &key (startl 0) (start] 0) endl end2<br />

str1ng-not-greaterp string 1 string2 &kcy (slartl 0) (slart20) endl end2<br />

Each of these r<strong>et</strong>urns t if the specified subsequences satisfy the specified ordering<br />

predicate. Basic<strong>al</strong>ly. the comparison is d<strong>et</strong>ermined by the first character in the<br />

subsequences which differs (see char-Iessp ctc.. page 95). unless the subsequences are<br />

equa~ in which case a shorter subsequence is t'less than".<br />

As a speci<strong>al</strong> upwards-compatibility hack, string-Iessp (but not the other functions) will<br />

accept its arguments position<strong>al</strong>ly rather than by-keyword.<br />

string- string 1 strillg} &kcy (slarIIO) (slort20) end! end}<br />

string/- .~tringl string} &key (startlO) (start) 0) endl end]<br />

str 1 ng< string I string} &kcy (start 10) (slart20) elldl end2<br />

string- slringi slring2 &key (startIO) (starI20) endl end2<br />

MC:<strong>NIL</strong>MAN:STRING 54<br />

23-DEC-83<br />

~ .. . ... -


Extracting Characters from Strings 114 NH. Manu<strong>al</strong><br />

str i ng> string! string] &key (slartl 0) (sta,,20) elldl elld2<br />

These functions are similar to those above, but do a case dependent character comparison;<br />

that is, they compare the characters like char:: <strong>et</strong>c. (page 95), rather than char-equ<strong>al</strong>.<br />

]3.3 Extracting Characters from Strings<br />

char Siring index<br />

R<strong>et</strong>urns the indexth character (zero-origined) of the string sIring. as a character object.<br />

sIring must be a string.<br />

Because sIring must hea string. the result uf char will <strong>al</strong>ways Stllisfy string-char-p (page<br />

19), with <strong>al</strong>l that that implies.<br />

schar simple-string index<br />

This is like char except that the string must be a simple string. This routine can be<br />

efliciently coded by the <strong>NIL</strong> compiler.<br />

Like char. schar may be used with s<strong>et</strong>f to store into the string.<br />

13.4 String Creation<br />

make-string length &key :initi<strong>al</strong>-efement<br />

Makes a string irl1gln iong. Since no compiicated array options may· be specI"ed. thIS wiJI<br />

<strong>al</strong>ways be a simple-string. initi<strong>al</strong>-elrment must be a character which satisfies stringchar-p;<br />

if it is specified. the r<strong>et</strong>urned string contains that charactcrin every element<br />

If initi<strong>al</strong>-element is 110t supplied. the contents of the r<strong>et</strong>urned string is undefined by<br />

CO\1MON USP. <strong>NIL</strong>. which abhors uniniti<strong>al</strong>ized memory. will initi<strong>al</strong>ize it to zeros (which<br />

happen to be, but may not <strong>al</strong>ways be, the character # \Null). If <strong>NIL</strong> were to be<br />

transported to another operating system with different virtu<strong>al</strong> memory facilities, then this<br />

could change incompatibly.<br />

string-length Siring<br />

R<strong>et</strong>urns the length of the string sIring. string must be a string; it is not coerced.<br />

For COMMON USP, this function is superceded by the generic length function (page 49).<br />

There shou1d be no noticeable efficiency difference b<strong>et</strong>ween length and string -length. Of<br />

course, string-length will complain if its argument is nota string, whereas length wilt<br />

accept any sequence, including nit<br />

str1ng-upcase Slrillg &.key (slartO) end<br />

stri ng-downcase SIring &1cey (start 0) end<br />

R<strong>et</strong>urns a copy of SIring with <strong>al</strong>l characters converted as by char-upcase (or chardowncase).<br />

If start and/or end arc supplied. then only the specified subsequence of the<br />

result is affected: the result <strong>al</strong>ways is the &1melength as SIring. That is. string-upcase<br />

could have been defined as<br />

MC:NfLMAN;STRJNG 54<br />

2.1-I)EC-83


· - ~"''''"<br />

-..w.t"""'_.....,..._______<br />

------~--------------'~-.--~---,----------------<br />

<strong>NIL</strong> Manu<strong>al</strong> 115 More String Functions<br />

(defun string-upcase (string &key (start 0) end)<br />

{nstring-upcase (copy-seq string) :start start :end end»<br />

If no characters of the string are affected by the conversion. one may not depend on<br />

wh<strong>et</strong>her the result is string itself or a copy of it; to guarantee a copy, use copy-seq and<br />

nstring-upcase. as in the above example.<br />

nstring-upcase siring &key (stanO) end<br />

nstri ng- downcase siring &key (slarlO) end<br />

These rOlltines destructively con\'crt <strong>al</strong>l of the characters in the specified suhsequcnce of<br />

slrill~ to upper- or lower-case. siring is r<strong>et</strong>urncd.<br />

string-trim character-bag string<br />

S tr 1 ng -1 eft -tr 1m character-bag string<br />

str i n9 - ri ght - tr 1 m character-bag string<br />

Thesc routines rcturn a substring of siring resulting from trimming the characters in thc<br />

"This is a test. "<br />

13.5 l\lore String Functions<br />

The functions in this section are not provided by COMMON USP, but are typic<strong>al</strong>ly inherited<br />

from LISP MACHI:\E LISP. and are heavily used in <strong>NIL</strong>. That is <strong>al</strong>so why they havc not y<strong>et</strong> been<br />

convcrted to takc kcyworded argumcnts (<strong>al</strong>though some of them may be in the future).<br />

str1 ng-append &rcst strings<br />

R<strong>et</strong>urns a string which is the concatenation of <strong>al</strong>l the strings. The arguments are coerced<br />

to strings using string; in this it differs from the generic sequence function concatenate<br />

(page 50), which will not accept symbols, but will accept sequences (of characters) other<br />

than strings.<br />

substring string start &option<strong>al</strong> end<br />

R<strong>et</strong>urns the substring of string (coerced to a string using string) from the index start up<br />

to but not including end. which defaults to thc length of string if nil or not specificd. If<br />

the specified subsequence is the entire string. one may not depcnd on wh<strong>et</strong>her the<br />

r<strong>et</strong>urned result is string itself, or a copy; to guarantee a copy. subseq (pagc 50) may be<br />

used-howcver. subseq neither restricts its input to strings nor coerces symbols to strings.<br />

string-reverse string<br />

str1ng-nreverse Siring<br />

These are pr<strong>et</strong>ty much superceded by reverse (page 52) and nreverse (page 52). Notc<br />

that for string - nreverse. Siring must be a rc<strong>al</strong> string bccause it is destructively reversed;<br />

string-reverse will accept a symbol and rcturn a string.<br />

MC:<strong>NIL</strong>MAN:STRING 54<br />

23-DEC-83


Implementation Suhprimitivcs 116<br />

N I J. M~Ulu<strong>al</strong><br />

s t r 1 n 9 - sa arc h -c h a r char sIring &optionaJ (from 0) 10<br />

string-reverse-search-char char string &option<strong>al</strong> from (tvO)<br />

str1ng-search-not-char char SIring &option<strong>al</strong> ({ramO) 10<br />

str1ng-revarsa"'s8arch-not-char char slrillg &option<strong>al</strong> from (toO)<br />

str1 ng-saarch-s<strong>et</strong> char-s<strong>et</strong> string &option<strong>al</strong> (from 0) 10<br />

str1ng-raverse-saarch-s<strong>et</strong> char-s<strong>et</strong> string &option<strong>al</strong> from (toO)<br />

string-search-not-s<strong>et</strong> cha,..s<strong>et</strong> string &option<strong>al</strong> (fromO) 10<br />

str1ng-reverse-saarch-not-s<strong>et</strong>('ha,..sl'l string &option<strong>al</strong> from (100)<br />

char-srt is coerced into a sequence of characters: it should be a string. or a list or vector<br />

of ohjects acceptable to character (page 96).<br />

str i ng-search key SIring &option<strong>al</strong> (from 0) to<br />

str 1 ng - reverse - search key SIring &option<strong>al</strong> from (/00)<br />

Ll6 Implementation Subprimitives<br />

Th~ roulines descrihed in thb section are very fllst routines pnmltlve'S which arc orienled<br />

toward~ being open-compiled. As such. the}' perfonn very few nic<strong>et</strong>ies Jikeargumelll d<strong>et</strong>~lUlting.<br />

The versions available in the interpr<strong>et</strong>er probably will do some error checking~ but don't count on<br />

it. These are the Sluff' of which higher-level routines are made. '111ose which lake string<br />

arguments only accept simple strings.<br />

%s tr1 ng- cons length jill-character<br />

Creates a primitive string length long. filled with the character jill-character, C<strong>al</strong>ls to<br />

make-string will compile into c<strong>al</strong>ls to this. if possible. so one should not go out of the<br />

way to use this,<br />

%str1 ng-posqcharacter string index count<br />

This searches through string starting at index and proceeding for count characters for the<br />

character character. If it is found. then the index at which it occurs is r<strong>et</strong>urned;<br />

otherwise nil is r<strong>et</strong>urned. This primitive only looks at the code attribute of character.<br />

ignoring the rest<br />

%str1ng-eqv string! string] index! index} count<br />

Rcturnst if the substrings of string I and string2 defined by index!, index2. and count<br />

arc string = -that is, the same, with case being significant.<br />

%str1ng-replace destination source deslillation-index source-index counl<br />

This transfers COUllt characters from the simple-string source to the simple string<br />

des/ination, starting at the given indices.<br />

%str1 ng-trans 1 ate destillation source tr<strong>al</strong>lsl<strong>al</strong>ion-table destination-index source-index counl .<br />

This is a slightly hairier version of %string-replace, Instead of the characters being<br />

transferred liter<strong>al</strong>ly. the code of each character taken· from the string source is used as an<br />

index in the string tr<strong>al</strong>lslation-table to obtain the code to store instead. For example,<br />

string - upcase could be defined<br />

MC:NII.MAN:STRING 54<br />

23-DEC-83


Nil. Manu<strong>al</strong> 117 Imp1cmcnt~lion Subprimitives<br />

(defun string-upcase (string<br />

&aux (len (string-length string»))<br />

(%string-translate<br />

(make-string len) string *:character-upcase-table<br />

o 0 len»<br />

where *:character-upcase-table has as its v<strong>al</strong>ue a string char-code-limit long whose<br />

ith character is the uppercase version of the character with code i. Note that this<br />

definition of string-upcase is not correct if the input sIring is not a simple-string. and<br />

note <strong>al</strong>so how this relates to how string-char-p is defined.<br />

String hashing in ~IL<br />

is ultimately performed by the eRe instruction.<br />

%str1ng-hash sIring erc-tab/e slar! ('(JUllI<br />

This performs a hash comput..1tion on the substring of SIring starting at character starT and<br />

proceeding for cowll characters. ere-table must be a simple bit vector 512 bit.; (16 \'AX<br />

]ongwords) long: it should contain the hash polynomi<strong>al</strong> for usc by the eRC instruction.<br />

Sever<strong>al</strong> hash polynomi<strong>al</strong> tables arc pf(l\'ided (they arc listed below). The hash<br />

computation is initi<strong>al</strong>ly -1: tllt.~ result is r<strong>et</strong>urned as a signed 'II fixl1um-that is. a 32-bit<br />

word with the lop two bits shifted otl'. Consult the VAX architecllIre manu<strong>al</strong>. or some<br />

other DEC documentation. to s<strong>et</strong> up other hash polynomi<strong>al</strong>s.<br />

For this to be properly useful for increment<strong>al</strong>ly generating CRe computations. this<br />

primitive will have to be changed to somehow input and output full 32-bit quantities;<br />

*:autod1n-11-hash-polynom1<strong>al</strong><br />

*:cc1tt-hash-polynom1<strong>al</strong><br />

*:crc-16-hash-polynomi<strong>al</strong><br />

This is the one <strong>NIL</strong> uses for doing intern and sxhash of strings.<br />

J;ariablc<br />

Variable<br />

Variable<br />

MC:<strong>NIL</strong>MAN:STRING 54<br />

23-DEC-83


-. • • • _': - " .~.<br />

• - - - '.' - • ," .:: • • .-' -- .'. - • •<br />

Hashing 118 Nil. Mamwl<br />

14. Hashing<br />

Nil. supports a COMMON JJSP compatible hash-table facility. This will eventu<strong>al</strong>ly include the<br />

ability to have a hash-table from which associations can be garbagc-conected.<br />

14.1 Hash Tables<br />

The following routines are COMMON I.ISP compatible:<br />

make-hash-table &key :test :rehash-threshold :rehash-size :size<br />

Cr{,~ltcs .. hash tahle. The tcs/ m,l}, be one of # 'eq.' # 'eql. or # 'equ<strong>al</strong>. <strong>NIL</strong><br />

,uJditionaHy provides some others it is able to perfonnsignific,mt optimizations on as<br />

primith'e (see hclow). Note t11m fi.lr 1'11. () usc some predicate it must know how to<br />

compute a hash code compatible with that predicate'snotion of equ<strong>al</strong>ity: thUS. not just<br />

any predicate is acceptable.<br />

g<strong>et</strong> hash kcy haslf"lable &option<strong>al</strong> dejault<br />

This r<strong>et</strong>urns two v<strong>al</strong>ucs. If there is an entry for key in hash-lab/e. then this r<strong>et</strong>urns as its<br />

v41lues the v<strong>al</strong>ue associated with key. and t. Otherwise. it r<strong>et</strong>urns default. and nit<br />

g<strong>et</strong>hash may be used with s<strong>et</strong>f to add an entry to (or replace an entry in) a· hash table.<br />

remhash key hash-table<br />

Removes the cntry associated with key from hash-Iable.<br />

cl rhash hash-fable<br />

Removes <strong>al</strong>1 entries from hash-lable.<br />

hash - tab 1 e - count hash-table<br />

R<strong>et</strong>urns the number of entries in hash-lable.<br />

14.1.1 Addition<strong>al</strong> Hash-Table Predicates<br />

<strong>NIL</strong> addition<strong>al</strong>ly offers the following predicates for hash-tables:<br />

string -equ<strong>al</strong><br />

string= '<br />

associating hashing routines with predicates, making this list extensible?<br />

MC:NII.MAN;HASH20<br />

23-DEC-83<br />

".;,. ..... ~ , - ~. I , ~<br />

. ~ -. .~: ~ - ~ ~ -, : : ~<br />

- .... I " • • _ ..<br />

. .". v. . " '. f' ~"<br />

•<br />


<strong>NIL</strong> Manu<strong>al</strong> 119 Hash Functions<br />

14.2 I lash Functions<br />

A hash function for equ<strong>al</strong>ity predicate (p xl. x2) is a function which r<strong>et</strong>urns the same v<strong>al</strong>ue<br />

for <strong>al</strong>l x which are equiv<strong>al</strong>ent according to p. "The standard LISP hashing function is sxhash.<br />

which is defined according to the equ<strong>al</strong> predicate. sxhash is inherited from MACUSP. and is<br />

defined by CO~1MON LISP and LISP MACHINE LISP;<br />

Other hash functions are defined by ~IL. for use with other equ<strong>al</strong>ity predicates. Usu<strong>al</strong>ly they<br />

are not needed. because tJley are impJied in me use of a hash table utilizing a particular equ<strong>al</strong>ity<br />

predicate. Ry convention. <strong>al</strong>l 'II. hashing functions r<strong>et</strong>urn a non-negative fixnum: it is a fixnum<br />

for ease of computation. and non-negative to make modulus operations more trivi<strong>al</strong>.<br />

sxhas h ()~;ecl<br />

This is tJle gener<strong>al</strong> J .ISP hashing function. hased on the predicate equ<strong>al</strong> (page 20). hit<br />

.r<strong>et</strong>urns a non-negative integer: in <strong>NIL</strong>, this will <strong>al</strong>ways be a fixnum. Two objects which<br />

are equ<strong>al</strong> should <strong>al</strong>ways sxhash to me same tJling. If tJ1is is not true. then any hash<br />

~1hles which use sxhash and equ<strong>al</strong> will break. Note that hecause !'II will have a<br />

relocating garbage collector, the hash of In object should never be a function of the<br />

address of anything.<br />

str i ng-equa l-hash string<br />

This function r<strong>et</strong>urns a non-negative fixnulTI such tJlat for <strong>al</strong>l strings which are stringequ<strong>al</strong>.<br />

tJleir hashes computed by this function will be equ<strong>al</strong>.<br />

str1ng a -hash Siring<br />

Similar; defined by the predicate string = (page 113).<br />

sys: sxhash-comb1 ne {hash} +<br />

This macro might be useful to writers of :sxhash m<strong>et</strong>hods or speci<strong>al</strong> hashing functions. It<br />

is a canonic<strong>al</strong> way to combine a fixed number of hash codes. For example, the sxhash<br />

of a cons docs<br />

(sys:sxhash-combine (sxhash (car x)} (sxhash (cdr x)})<br />

The hashes are rotated some fixed amount d<strong>et</strong>ennined by the number of arguments, and<br />

crunched tog<strong>et</strong>her in some canonic<strong>al</strong> fashion. (There may be a limitation on the number<br />

of arguments which are handled, but this will work for some moderate number of<br />

arguments.)<br />

14.3 Symbol Tables<br />

Although one can use packages to implement symbol tables. and this has been recommended<br />

in the past. it is now b<strong>et</strong>ter to use a hash table based on the appropriate predicate. and storing<br />

'an appropriate object as the v<strong>al</strong>ue. For example, if one had been using a package as a symbol<br />

table and then using the symbol after interning it. a hash table could be used using string-equ<strong>al</strong><br />

or string = as the predicate (as appropriate) and putting a symbol in as the v<strong>al</strong>uc. Dcpending on<br />

what the symbol is used for. it may be b<strong>et</strong>ter to use a defstruct-created object instead: attributes<br />

can be accessed fasler off of this than as properties on the pliSl of a symbol. Secondarily. there is<br />

a moderate space inefficiency to gener3ting lots of v<strong>al</strong>ue ceBs in Nil" so instead of generating<br />

symbols and using their v<strong>al</strong>ue cells to store things is <strong>al</strong>so b<strong>et</strong>ter to usc a speci<strong>al</strong>ized structure.<br />

~1C:NII.MAN:H"SH 20<br />

2J-DFC-83


Symbol Tables 120 Nil. M,lnu<strong>al</strong><br />

When the ~n. package system is redone. the intcrna1 portion of that which docs simple<br />

symbol-table hacking will be made· available fi)r applications where that is truly nceded.<br />

~1C;NJL~1.\~:HASH 20


<strong>NIL</strong> Manu~l 121 Packages<br />

15. Packages<br />

Skctchy. This is <strong>al</strong>l going to brcak. either as a result of COMMON LISP or compl<strong>et</strong>e<br />

rcimplcmcntation and redesign or both.<br />

understanding of simple obarrays/ob/isls and interning is assumed below<br />

The basic idca of packages is that if an programs in a large messy environment like <strong>NIL</strong> use<br />

the same name-sp


Packages 122 <strong>NIL</strong> Manu<strong>al</strong><br />

A little thought «thOllt the use of the sys and glob<strong>al</strong> p~lckages in the ahove description will<br />

show that they should nO( be ordin


<strong>NIL</strong> Manu<strong>al</strong> 123 Modules<br />

15.1 Modules<br />

CO!\1!\10~ LISP defines a fairly simple way in . which one may name modules. declare that they<br />

have been loaded, and cause them to be loaded if they have not been. While t11is is intended to<br />

be used as a part of the COMMON LISP package system. it is fairly independent and can be used<br />

without it. Here it is.<br />

In this sense. a module (not to be confused with the <strong>NIL</strong> data type module which will be<br />

renamed someday) is simply an independent subsystem which is treated as a unit. A module can<br />

come from one or more files: the' number is irrelevant other than to the loading process.<br />

CO\1\10,\ liSP modules arc referenced by name: functions which take a module name may he<br />

given either a string or a symhol. In the module name. case mailers. so. f()r instance. "LSS" is<br />

not the same module name as "Isb".<br />

• modul as.<br />

Variable<br />

This variable has as its v<strong>al</strong>ue a list of the names of <strong>al</strong>l the modules which have been<br />

provided (see be1


Modules 124<br />

NII~ Manu<strong>al</strong><br />

note-modu18-pathname module-1lome po/hllam!'<br />

This declares that in order to provide lIlodule-llame. p<strong>al</strong>/m<strong>al</strong>lle must be loaded. p<strong>al</strong>hllome<br />

may <strong>al</strong>so be a list of pathnames.<br />

Eventu<strong>al</strong>ly. higher-level ways of defining packages, systems. and modules wiU be defined.<br />

and use of note-modufe-pathname will be phased out.<br />

The only modules known about in advance by the <strong>NIL</strong> system right now LS8 and SIMP. Of<br />

course. as of this writing. the fc1cilitics documented in this. section haven °t even been inst<strong>al</strong>led y<strong>et</strong>.<br />

so there will probably be severa) tnoreshonly .<br />

...<br />

!\1C:NII.\1AN:PACKAG 17<br />

23-DEC-S3


<strong>NIL</strong> Manu<strong>al</strong> 125 Defstruct<br />

16. Defstruct<br />

) 6.1 Introduction<br />

This chapter is a modification of the description of defstruct appearing in the MacIisp<br />

Extensions Manu<strong>al</strong> [3]. There are three sorts of ~hangcs:<br />

(I) Del<strong>et</strong>ion of topics not applic~bJe) to <strong>NIL</strong>;<br />

(2) Del<strong>et</strong>ion of things which do not y<strong>et</strong> work in <strong>NIL</strong>;<br />

(3) Modifications of the defaults. as the <strong>NIL</strong> defstruct is intended to be upwards-compatible<br />

with the CO\1\HY\ IISP defstruct.<br />

For these reasons. some of Ule wording m~'y seem a bit strange. in that the origin<strong>al</strong> document is<br />

concerned with helping users write code compatible in differing l.isp implementations. defstruct<br />

is part of the ('0\1\10;\ I.ISJ> st4tndard (but not <strong>al</strong>l the parts of it). and the documentation on it<br />

will be fixed in the future. Any inaccuracies in this modification of it are purely the fault of<br />

GSB.<br />

The keywords which are used in defstruct arc <strong>al</strong>l interned in the keyword package. just like<br />

Olher keY\H)rds in :\11.. For compatibility with \tACI.ISP programs. howe":-f. defstruct \\-'ill accept<br />

UlOse 1101 in me keyword package. Convcrsely. the MAC'I.ISP def.~truct will check f(lr symbols<br />

which have a leading "." in their names. In !'IL. one should use the colons for stylistic<br />

consistcncy.<br />

16.2 A Simple Example<br />

defstruct<br />

defstruct i~ a macro defining macro. The best way to explain how it works is to show a<br />

sample c<strong>al</strong>l to defstruct. and thcn to show what macros are defincd and what each of<br />

them does.<br />

Sample c<strong>al</strong>l to defstruct:<br />

(defstruct (elephant (:type :list»<br />

color<br />

(size 17.)<br />

(name (gensym»)<br />

This fonn expands into a whole rat's nest of stuff, but the effect is to define five macros:<br />

elephant-color, elephant-size. elephant-name. make-elephant and <strong>al</strong>ter-elephant. Note that<br />

none of these symbols appeared in the origin<strong>al</strong> form, they were created by defstruct. The<br />

definitions of color. size and name are easy. they expand as follows:<br />

(elephant-color x) ==> (car x)<br />

(elephant-size x) ==> (cadr x)<br />

(elephant-name x) ==> (caddr x)<br />

You can see that defstruct has decided to implement an elephant as a list of uucc things~ its<br />

color, its size and its name. The expansion of make-elephant is somewhat harder to explain,<br />

l<strong>et</strong>'s look at a few cases:<br />

MC:<strong>NIL</strong>MAN;DEFSTR 91<br />

23-DEC-83


57 - -.- v 'to ,<br />

I<br />

Syntax of de fstruct 126<br />

Nil. Milfiu<strong>al</strong><br />

(make-elephant) ==> (list nil 17. (gensym»<br />

(make-elephant :color 'pink) ==> (list 'pink. 17. (gensym»<br />

(make-elephant :name 'fred :size 100)<br />

==> (list nil 100 'fred)<br />

As you can sec, make-elephant takes a "sctq-stylc" list of pan names and forms, and<br />

expands into a c<strong>al</strong>l to list that constructs such an elephant. . Note that the unspecified pans g<strong>et</strong><br />

defaulted to pieces of code specified in the origin<strong>al</strong> caU to defstruct. Note <strong>al</strong>so that the order of<br />

the sctq·style arguments is ignored in constructing the c<strong>al</strong>l to list. (In the example. 100 is<br />

ev<strong>al</strong>uated before 'fred even though 'fred came first in the make-elephant form.) Care should<br />

thus he taken in usjng code with side effects within the scope of a make-e1ephant. (This<br />

particular hehaviour will be "fixed" by (,O\1MO~ LISP. hut has not y<strong>et</strong> been worked into \11.)<br />

Fin<strong>al</strong>ly, wke note of the fact thai the (gensym) is ev<strong>al</strong>uated el'C'IJ' lime a new elephmltis creilled<br />

(unless you override it).<br />

The explanation of what <strong>al</strong>ter-elephant docs is delayed until section 16.4.3. page 129~<br />

So now you know how to construct a new elephant and how to examine the parts of an<br />

elcph.mt. but how do you ch.mgc the pare; of an <strong>al</strong>ready existing elephant? The answer is to use<br />

the s<strong>et</strong>f m,tcro (section 5.9 t page 38).<br />

_(s e t f (e 1 e p han t - n arne x) 'b i 11 ) = = > ( s<strong>et</strong> f (c add r x) , bill )<br />

which is what you want.<br />

A nt1 th!lt ~5 jU5t about an t"~rc -is t{' defstruct: you now know enough to use it in your cede.<br />

but if you want to know about <strong>al</strong>l its interesting features, then read on.<br />

16.3 Syntax of derstruct<br />

The gener<strong>al</strong> fonn of a defstruct fennis:<br />

(defstruct (name opt;o"..1 0pl;0n-2 ••• option-n)<br />

slot-description-I<br />

slot-description-2<br />

s/ol-descriplion-m)<br />

name must be a symbol. it is used- in constructing names (such as_ "make-elephant") and it is<br />

given a defstruct-description property of a structure that describes the structure compl<strong>et</strong>ely.<br />

Each oplion-i is either the atomic name of an option. or a Ust of the form (option-name arg •<br />

res/). Some options have defaults for arg; some will complain if they are present without ail<br />

argument: some options complain jf they are present with -an argument. The intcrpr<strong>et</strong>ationof rest<br />

is up to the option in question. but usu<strong>al</strong>ly it is expected to be nit<br />

Each SIOI-dcscriplioll-j is either the atomic name of a slot in the structure. or a list of the<br />

form (slot-Ilome illit-C'ode). or a list of byte field specifications. illil-code is used by constructor<br />

macros (such as make-<strong>et</strong>ephant) to initi~1ize slots not specified in the c<strong>al</strong>l to the constructor. If<br />

the illil .. code is not specified. then the slot is initi<strong>al</strong>ized to whatever is most convenient. (In the<br />

elephant example, since the structure was a list. nil was used. If _ the structure had been a<br />

MC:<strong>NIL</strong>MAN:DEFSl'R 91<br />

23-DEC-83


N II. Manu<strong>al</strong> 127 Options to defstruct<br />

fixnurn array. such slots would be fined with zeros.)<br />

A bytc field specification looks like: (field-name bytespec) or (field-name bylespec illit-code).<br />

Notc that since a byte field specification is <strong>al</strong>ways a list. a list of byte field specifications can<br />

never be confused with the other cases of a slot description. The byte field feature of defstruct<br />

may be undergoing change in !'I:II. due to the incompatible change of bytespec format (see section<br />

10.9. page 84). so is discouraged for the present·<br />

16.4 Options to defstruct<br />

The following sections document each of the options defstruct understands in d<strong>et</strong>ail.<br />

On the Lisp Machine and in ~II..<br />

package.<br />

an these defstruct options are interned on the keyword<br />

16.4.1 :type<br />

The :type option specifics what kind of lisp object defstruct is going to use to implement<br />

your structure. and how that implementation is going to be carried out. The :type option is<br />

illeg<strong>al</strong> without an argument. If the :type option is not specified. then defstruct will choose an<br />

appropriate default: in I'lL. defstruct will implement the structure as a vector-like object. which<br />

will be defined as a type whose name is the name given to defstruct. One can then check for<br />

objects ot thiS type with typep. (This dittcrs from the way defstruct currently operates in<br />

\1:\('I.ISI> and I.IS}> M:\C'IIINF LISP.) It is possible for the user to teach defstruct new ways to<br />

implement structures, the interested reader is referred to section 16.6, page 138, for more<br />

information. Many useful types have <strong>al</strong>ready been defined for the user. A table of these "built<br />

in" types follows.<br />

:Iist<br />

:named-list<br />

:tree<br />

:list.<br />

Uses a list This is the default in MULTICS MACUSP.<br />

Like :list, except the car of each instance of this structure will be the name<br />

symbol of the structure. This is the only "named" structure type defined on<br />

Multics and is the default named type there. (See the :named option documented<br />

in section 16.4.4, page 131.)<br />

Creates a binary tree out of conses with the slots as leaves. The theory is to<br />

reduce car-cdring to a minimum. The :include option (section 16.4.9, page 133)<br />

does not work with structures of this type.<br />

Similar to :list. but the 1ast slot in the structure wi11 be placed in the cdr of the<br />

fin<strong>al</strong> cons of the list. Somc people caB ohjects of this type ttdotted lists". 111C<br />

:include option (section 16.4.9. page 133) does not work with structures of this<br />

type.<br />

MC:NII.MJ\N:DEFSTR 91<br />

2J-I)EC-8J


Options to d<strong>et</strong>struct 128 <strong>NIL</strong> Manuill<br />

: array<br />

:sfa<br />

:vector<br />

Uses an array object (not a symbol with an array property). This is the default on<br />

Lisp Machines. Eventu<strong>al</strong>ly. many of the same hairy array options which defstruct<br />

supports on the Lisp Machine will be supported in <strong>NIL</strong>; at this time. however.<br />

<strong>NIL</strong> users are advised to just usc the default, or perhaps :vector.<br />

Uses an SFA. The constructor macros for this type accept the keywords :sfafunction<br />

and:sfa-name. Their arguments (ev<strong>al</strong>uated. of course) are used.<br />

respectivcly. as the function and the printed represenwtion of the SFA. See <strong>al</strong>so<br />

the :sfa-function (~cli(}n 16.4.12. page 134) and :sfa-name (section 16.4J3. page<br />

135) options. (SFAs ,tre clvailahle in ~n. for compatibility with PDP-IO \1 ACIISI).<br />

They should not nonn<strong>al</strong>ly be used. and HfC not documented in the 'II m~lJlu<strong>al</strong>.)<br />

Uses an vector. This will be a simple-vector.<br />

:nl\med - vector<br />

I -ike \ ector. ex,:cpt clement number 0 illways contains the n(lme symbol of the<br />

structure. Note thUl this is 110/ Ule default lIdmcd type in Nil .• :extend is.<br />

:extend<br />

'Ibis is the default named type in ~IL. Nonn<strong>al</strong>ly you don't need· to know that it<br />

h~~ thi" w~ird T1;l1T'!('. h~m,se thi5 has bc~n the d~f:m!! dcfS!!"uct typ~ if :namse is<br />

specified for a \\'hile. and it is now the def4Juh type period. See <strong>al</strong>so the :classsymbol<br />

option (section 16.4.11, page 134).<br />

) 6.4.2:constructor<br />

The :constructor option specifics. the name to be given to the constructor macro. Without an<br />

argumen~ or if the . option is not present. the name defaults to the concatenation of "make..·' with<br />

the name of the structure, If the option is given with an argument of nil. then no constructor is<br />

defined. Otherwise the argument is the name of the constructor to define. NonnaUy the syntaX<br />

of the constructor defstruct· defines is:<br />

( COIlSlTUClo~nQme<br />

keyword-J code-J<br />

keyword-2 codeo2<br />

keyword-n code-n)<br />

Each keyword- i must be the name of a slot in the structure. or one of the speci<strong>al</strong> keywords<br />

<strong>al</strong>lowed for the particular type of structure being constructed. . All of these keywords are symbols<br />

interned in the keyword package. <strong>al</strong>though for upwards-compatibility (this is new behaviour) that<br />

is not required. For each keyword that is the name of a slot. the constructor expands into code<br />

to make an instance of the structure using ('odr-i to initi<strong>al</strong>ize slot keyword-i. Unspecified slots<br />

default to the forms given in the origin<strong>al</strong> defstruct fonn. Of, if none was given there. to some<br />

convenient v<strong>al</strong>ue such as nil or O.<br />

MC:<strong>NIL</strong>MAN:DEFSTR 91<br />

23-DEC-83


dieTl' r "TrT'erl;"" . pm'l<br />

7'$tMr7' 'Teitmr<br />

<strong>NIL</strong> Manu<strong>al</strong> 129 Options to defstruct<br />

For keywords that are not names of slots. the use of the corresponding code varies. Usu<strong>al</strong>ly<br />

it controls some aspect of the insUlnce being constructed that is not otherwise constrained. The<br />

only one of these which is used in <strong>NIL</strong> is the :sfa-function option (section 16.4.12. page 134).<br />

If the :constructor optior is given as (:eonstru<strong>et</strong>or Ilame arglis!). then instead of making a<br />

keyword driven constructor. defstru<strong>et</strong> defines a ttfunction style" constructor. The arglist is used<br />

to describe what the arguments to the constructor will be. In the simplest case som<strong>et</strong>hing like<br />

(:constructor make-foo (a b e» defines make-foo to be a three argument constructor macro<br />

whose arguments are lIsed to initi<strong>al</strong>ize the SIOLIi named a. band c.<br />

In addition. the keywords &option<strong>al</strong>. &rest and &aux are recognized in the argument list.<br />

They work in the way you might expect. but there are a few fine points worthy of explan


W ·lrV"·<br />

•<br />

130<br />

made to be the v<strong>al</strong>lie of slot s!o/-llome-; of that structurc. lbe slots are an <strong>al</strong>tcrcdin par<strong>al</strong>le1<br />

<strong>al</strong>ief <strong>al</strong>l code has been ev<strong>al</strong>uated. (Thus you can usc an <strong>al</strong>terant macro to exchange the contents<br />

to two slots.) As for the kcywordcd constructor macro. the s!ot-Ilame-i should be symbols interned<br />

in the keyword package. <strong>al</strong>though (again) that is not required.<br />

Example:<br />

(defstruct (lisp~hacker<br />

(favorite~macro-package<br />

(unhappy? t)<br />

(number-of-friends 0»<br />

(:type :11st)<br />

:conc-name<br />

:defau1t-pointer<br />

:a1terant)<br />

nil)<br />

(s<strong>et</strong>q lisp-hacker (make-lisp-hacker»<br />

Now we can perfonn a transfonnation:<br />

(<strong>al</strong>ter-lisp-hacker lisp-hacker<br />

favorite-macr0-package 'defstruct<br />

number-of-fribnds 23.<br />

unhappy? nil)<br />

==> «lambda (G0009)<br />

« lambda (GOOI1 GOOIO)<br />

(s<strong>et</strong>f (car G0009) 'defstruct)<br />

ls<strong>et</strong>t (caaar uOOOY) uOOll)<br />

(s<strong>et</strong>f (cadr G0009) GOOIO»<br />

23.<br />

nil»<br />

lisp-hacker)<br />

Although it appears from this example that your fonns will be ev<strong>al</strong>uated in the order in<br />

which you wrote them~ this is not currently guaranteed.<br />

Alterant macros are particularly good at simultaneously modifying . sever<strong>al</strong> byte fields that are<br />

<strong>al</strong>located from the same word. They produce b<strong>et</strong>ter code than you can by simply writing<br />

consecutive s<strong>et</strong>fs. They <strong>al</strong>so produce bener code when modifying sever<strong>al</strong> slots of a structure that<br />

uses the :but-first option (section 16.4.17, page 135).<br />

For defstruct types whose accessors take more than one argument. <strong>al</strong>l of those arguments<br />

must be supplied to the <strong>al</strong>terant macro in place of just the usu<strong>al</strong> one. (Sec section 16.6.3.2, page<br />

140 for how accessors with more than one argument can come to be, there are no built-in<br />

defstruct types with this propcny.)<br />

MC:NII.MAN:DEFSTR 91<br />

23-DEC-83<br />

. - .<br />

- -<br />

. . -<br />

, ~ < • .. • ~ ~ ." ~ .. _ ....: - ~ , • ., ~ ...... _ ~.., ~ ~ , • J. • f


3 - -<br />

2<br />

~<br />

<strong>NIL</strong> Manu<strong>al</strong> 131 Option!'. to dcfstruct<br />

16.4.4 :named<br />

This option tells defstruct that you desire your structure to be a "named structure". In PDP-<br />

10 \1ACl.ISP this means you want your structure implemented with a :named-hunk, :named-list<br />

or :named-vector. On a Lisp Machine this indicates that you desire either a :named-array or a<br />

:named-array-Ieader or a :named-list. On Multics this indicates that you desire a :named-list.<br />

In ~IL this indicates that you desire a :extend. a :named-vector or a :named-list. defstruct<br />

bases its decision as to what named type to use on whatever v<strong>al</strong>ue you did or didn't give to the<br />

:type option: in <strong>NIL</strong>. the default named type is :extend. and :named is the default-the<br />

significance of this was explained in section 16.4.1. page 127. It is an error to usc this option<br />

with an argument.<br />

16.4.5 :predicate<br />

The :predicate option causes defstruct to generate a predicate to recognize instances of the<br />

stmcllIre. Natur<strong>al</strong>ly it nnh' works for some ~efstruct types. Currently it works for <strong>al</strong>l the named<br />

types as we11 as the types :sfa {PDP-tO \1ACUSf) and :\IL only) and :extend (:\11. only). The<br />

arg.ulllcnt to the :predicate option is the name of the predicate. I f it is present without an<br />

argument, then the name is formed by concatenating "_p" to the end of the name symbol of the<br />

stmcture. If the option is not present then no predicate is generated. Example:<br />

(defstruct (foo :named :predicate)<br />

foo-a<br />

foo-b)<br />

defines a single argument function. foo-p. that is true only of instances of tJlis stmcture.<br />

16.4.6 :print<br />

The :print option <strong>al</strong>10ws the user to control the printed representation of his structure in an<br />

implementation independent way:<br />

(defstruct (pair :named<br />

pair-first<br />

pair-second)<br />

(:print "{-S . -S}"<br />

(pair-first pair)<br />

(pair-second pair»)<br />

The arguments to the :print option are used as if they were arguments to the format function<br />

(page 187). except that the first argument (the stream) is omitted. They are ev<strong>al</strong>uated in an<br />

environment where the name symbol of the structure (pair in this case) is bound to the instance<br />

of the structure to be printed.<br />

This option presently only works on Lisp Machines and in <strong>NIL</strong>. using the defstruct types<br />

:named-array and :extend respectively. We hope to make it work in rDP-10 \1ACl.lSP for the<br />

:named-hunk type soon. In MULTICS MACLlSP. this option is ignored. Notice that if you just<br />

specify the :named option without giving an explicit :type option. each defstruct implementation<br />

will default to a named type that can control printing if at <strong>al</strong>l possible.<br />

MC:NII.MAN:DEFSTR 91<br />

23-DFC-83


Optiuns to defstruct 132 Nil. M.tnu<strong>al</strong><br />

16.4.7 :default-pointer<br />

Norm<strong>al</strong>ly the accessors are defined to be macros of exactly one argument. (They check!) But<br />

if the :default-pointer option -is present then they will accept zero or one argument. When used<br />

with one argument. they behave as before. but given no. arguments. they expand as if they had<br />

been c<strong>al</strong>led on the argument to the :default .;.pointer option. An example is probabJy caned for:<br />

(defstruct (room (:type :tree)<br />

(:default-pointer •• current~room •• )}<br />

(room-name 'y2)<br />

(room-contents-list nil»<br />

Now the accessors expand as follows:<br />

(room-name x)<br />

(room-name)<br />

==><br />

==><br />

(car x)<br />

(car •• current-room •• )<br />

If no argu~ent is given to the :default-pointer option. then the name of the stnJcture is<br />

used as the "default pointer". :default- pointer is most often used in this fashion.<br />

16.4.8 :conc"name<br />

Frequently <strong>al</strong>l the accessor macros of a· stnt<strong>et</strong>ure will want to have names that begin the same<br />

way: usu<strong>al</strong>ly with the name of the stnlcture followed by a dash. The :conc-name option Clllows<br />

the user to specify this prefix. Its argument should be a symbol whose print name will be<br />

concatenated onto the front of the slot names when forming the accessor macro names. If the<br />

argument is not given. then the name of the structure fbl10wed by a dash is used. as it is if the<br />

:conc-name option is not prcscnL(This is different than it used to be!) If it is desired that the<br />

slot names. as specified. be used' as the accessor macros. then (:conc-name nil) may be used.<br />

An example illustrates a common use of the :conc-name option <strong>al</strong>ong with the :default-pointer<br />

option:<br />

(defstruct (location :default-pointer<br />

:conc-name)<br />

(x 0)<br />

(y 0)<br />

(z 0»<br />

Now if you say<br />

(s<strong>et</strong>q location (make-location x 1 y 34 z 5»<br />

it will be the case that<br />

(location-y)<br />

will r<strong>et</strong>urn 34. Note wen that the name of the slot ("ytt) and the name of the accessor macro for<br />

that slot ("location y") are different<br />

w<br />

MC:NII.MAN:DEFSTR 91<br />

- -, ,- - - . '- ' . -' ,- -, _:'" ' - - .: , ' -<br />

- -' " ~ ~~ -' '.' -~, ~~ '-~ '.':, " - ". ' ' - " --, ,<br />

-, ,- , - ~ :' -' , . ';: -,'. , - -. .


WoW'OM t<br />

<strong>NIL</strong> Manu<strong>al</strong> 133 Options to defstruct<br />

16.4.9 :include<br />

The :include option inserts the definition of its argument at the head of the new structure's<br />

definition. In other words. the first slots of the new structure are equiv<strong>al</strong>ent to (Le. have the<br />

same names as. have the same inits as. <strong>et</strong>c.) the slots of the argument to the :include option.<br />

The argument to the :include option must be the name of a previously defined structure of the<br />

same type as the new one. If no type is specified in the new structure, then it is defaulted to<br />

that of the included one. It is an error for the :include option to be present without an<br />

argument. Note that :include does not work on certain types of structures (e.g. structures of type<br />

:tree or :Iist.). Note <strong>al</strong>so that the :conc-name, :default-pointer. :but-first and :c<strong>al</strong>lableaccessors<br />

options only apply to the accessors defined in the current defstruct: no new accessors<br />

arc defined f(.lf the included slots.<br />

An example:<br />

,(defstruct (person (:type :list})<br />

name<br />

age<br />

sex)<br />

(defstruct (spaceman (:include person)<br />

(:conc-name nil)<br />

:defau1t-pointer)<br />

helm<strong>et</strong>-size<br />

(favGrit~-b~v~rag~ 'tang})<br />

Now we can make a spaceman like this:<br />

(s<strong>et</strong>q spaceman (make-spaceman :name 'buzz<br />

:age 45.<br />

:sex t<br />

:helm<strong>et</strong>-size 17.5»<br />

To find out interesting things about spacemen:<br />

(helm<strong>et</strong>-size)<br />

==> (cadddr spaceman)<br />

(person-name spaceman) ==> (car spaceman)<br />

(favorite-beverage x) =:> (car (cddddr x»<br />

As you can see the accessors defined for the person structure have names that start with<br />

"person-" and they only take one argument. The names of the accessors for the last two slots of<br />

the spaceman structure are the same as the slot names, but they <strong>al</strong>low their argument to be<br />

omitted. The accessors for the first three slots of the spaceman structure are the same as the<br />

accessors for the person structure.<br />

Often. when one structure includes another. the default initi<strong>al</strong> v<strong>al</strong>ues supplied by the included<br />

structure will be undesirable. These default initi<strong>al</strong> v<strong>al</strong>ues can be modified at the time of inclusion<br />

by giving the :include option as:<br />

(: include name new-init-] ••. new-fnil-n)<br />

Each Ilcw-fnit-i is either the name of an included slot or of the fonn (included-slot-name new-init).<br />

If it is just a slot name. then in the new structure (the one duing the including) that slot will<br />

have no initi<strong>al</strong> v<strong>al</strong>ue. If a new initi<strong>al</strong>" v<strong>al</strong>ue is given. then that code replaces the old initi<strong>al</strong> v<strong>al</strong>ue<br />

code for that slot in the new structure. The included structure is unmodified.<br />

MC:NII.MAN:DEFSTR 91<br />

23-DEC-83


Options to defstruct 134 <strong>NIL</strong> Manu<strong>al</strong><br />

16 .• 4.10 :copier<br />

This option causes defslruct to generate a single argument function that will copy instances of<br />

this structure. The argument to the :copier. option is the name of the copying function. If this<br />

option is present without <strong>al</strong>l argument. then the name is formed by concatenating "copy-" with<br />

the name of the structure.<br />

Example:<br />

(defstruct (coat-hanger (:type :list) :copier)<br />

current-clos<strong>et</strong><br />

wire-p)<br />

Gen(.~r'llcs a function ~Ipproximatcly like:<br />

(defun copy-coat-hanger (x)<br />

(list (car x) (cadr x»)<br />

16.4.11 :class .. symbol<br />

For use with tlle :extend defstruct type ~l\·ai1ahle only in :\11 (section Io.'U. page 128). this<br />

option <strong>al</strong>lows the lIser to control hem' the flavor definition is pcrfimlled. '( his option IIIWil be<br />

given a variable name as an argument: the v<strong>al</strong>ue of that variable is used as the flavor (class)<br />

object of the object which the defstruct-defined constructor will create. defstruct wi11 not define<br />

the flavor.<br />

This option W~)S origin<strong>al</strong>ly implemented for bootstrapping purposes. so that typed objects in<br />

!':Il. could be created before the flavor system was fully loaded. Pventu<strong>al</strong>ly it will be fully<br />

outmoded by extensions to the flavor system, which <strong>al</strong>ready has the capability of defining accessor<br />

macros for instance variables.<br />

16.4.12 :sfa-function<br />

Available in PDP-IO MACUSP and in <strong>NIL</strong>. this optionaUows the user to specify the function<br />

that will be used in structures of type :sfa. Its argument should be a piece of code that ev<strong>al</strong>uates<br />

to the desired function. Constructor macros for this type of structure will take :sfa-function as a<br />

keyword whose argument is <strong>al</strong>so the code to ev<strong>al</strong>uate to g<strong>et</strong> the function. overriding any supplied<br />

in the origin<strong>al</strong> defstruct form.<br />

If :sfa ,..function is not present anywhere, then the constructor will use the name-symbol of<br />

the· structure as the function.<br />

MC:<strong>NIL</strong>MAN:DFFSTR 91<br />

23-DEC-83


.. "' m -f' - .,.o. d' T T C "5 - W)'W"'mlttnr ltV f'g' .,<br />

<strong>NIL</strong> Manu<strong>al</strong> 135 Options to defstruct<br />

16.4.13 :sfa-name<br />

Available only in PDP-IO MACI.ISP and 1'0:11.. this option <strong>al</strong>lows the user to specify the object<br />

that will be used in the printed representation of structures of type :sfa. Its argument should be<br />

a piece of code that ev<strong>al</strong>uates to that object. Constructor macros for this type of structure will<br />

take :sfa-name as a keyword whose argument is <strong>al</strong>so the code to ev<strong>al</strong>uate to g<strong>et</strong> the object to<br />

usc, overriding any supplied in the origin<strong>al</strong> defstruct fotm.<br />

If :sfa-name is not present anywhere. then the constructor will use the name-symbol of the<br />

stnlcture as the function.<br />

16.4.14 :sizc-symbol<br />

The :size-symbol option <strong>al</strong>lows a user to specify a symbol v.hose v<strong>al</strong>ue will be the "size" of<br />

the stnicture. The exact meaning of this varies, but in gener<strong>al</strong> this number is the one you would<br />

need to know if you were going to <strong>al</strong>locate one of these structures yourself. The symbol will<br />

have this v<strong>al</strong>lie both at compi1e time and' at run time. If this option is present without an<br />

argument. then the name of the structure is concatenated with "-size" to produce the symhol.<br />

16.4.15 :size-macro<br />

Similar to :size-symbol. A macro of no arguments is defined that eXPands into the size of<br />

the structure. The name of this macro defaults as with :size-symbol.<br />

16.4.16 :initi<strong>al</strong>-orrs<strong>et</strong><br />

lbis option <strong>al</strong>lows you to tell defstruct to skip over a certain number of slots before it starts<br />

<strong>al</strong>locating the slots described in the body. This option requires an argument. which must be a<br />

fixnum, which is the number of slots you want defstruct to skip. To make use of this option<br />

requires that you have some t:'UTliliarity with how defstruct is implementing you structure,<br />

otherwise you will be unable to make use of the slots that defstruct has left unused.<br />

16.4.17 :but-first<br />

This option is best explained by example:<br />

(defstruct (head (:type :list)<br />

nose<br />

mouth<br />

eyes)<br />

(:conc-name nil)<br />

(:default-pointer person)<br />

(:but-first person-head»<br />

So now the accessors expand like this:<br />

(nose x) ==> (car (person-head x»<br />

(nose)<br />

==> (car (person-head person»<br />

MC:NII.MAN:DEFSTR 91<br />

2J-DEC-8J


, • ,~ ~. ~ ~ - • ~.: M •<br />

Options to def.~lruct 136 <strong>NIL</strong> Mmlllill<br />

The theory is that :but-firsfs argument will likely be an accessor from some other stnlcture.<br />

and it is never expected dl<strong>al</strong> this structure will be found outside of that slot of that other<br />

structure. (In the example I had in mind that thefe was a person structure which had a slot<br />

accessed by person~head.) It is an effor for the :but-first option to be used without an<br />

argument.<br />

16.4.18 :c<strong>al</strong>lablc-accessors<br />

This option controls wh<strong>et</strong>her the accessors defined by defstruct will work as "function<strong>al</strong><br />

ar!!Ullll'1l1S" (as the first argument to mapcar. for example). On the I.isp Machine and in ~II.<br />

m.:ccs~or\ arc GJllahlc hy dcfitUll. but inPI>P-W \iA(,IISP it is cxpenshe to milke this work, so<br />

the~ arc only caHahle if you ask for it. (Currently on Multks the feaLUre doesn't work at <strong>al</strong>l ..•)<br />

The argument to this option is nil to indicate that the feature should he turned off. and t to turn<br />

the feature on .. If the option is present with no argument. then the feature is turned on.<br />

16.4.19 :cl'<strong>al</strong>-when<br />

Norm<strong>al</strong>ly the macros defined by defstruct are defined at c\<strong>al</strong>-time. compile-time 4md at loadtime.<br />

This option <strong>al</strong>lows the user to control this behavior. (:ev<strong>al</strong>-when (evaJ compile»~ for<br />

example. will c<strong>al</strong>ise the macros to he defined only when the code is nmning interpr<strong>et</strong>ed and<br />

inside the compiler. no trace of defstruct wiJ] be found when running compiled code. (See ev<strong>al</strong>when.<br />

page 25.}<br />

Using the :ev<strong>al</strong>-when option is preferahle to wrapping an evaJ-when around a defstruct .<br />

fonn. since nested ev<strong>al</strong>-whens can interact in unexpected ways.<br />

16.4.20 :property<br />

For each structure defined . by defstruct, a propeny list is maintained for the recording of<br />

arbitrary propenies about that structure.<br />

The :property option can be used to give a defstruct an arbitrary propeny.· (:property<br />

properly-name v<strong>al</strong>ue) gives the defstruct a property-name propeny of v<strong>al</strong>ue. Neither argument is<br />

ev<strong>al</strong>uated. To access the propeny list. the user will have to look inside the defstruct-description<br />

structure himself, he is referred to section 16.5, page 137. for more information.<br />

16.4.21 A Type Uscd As An Option<br />

In addition to the options listed above, any currently defined type (a leg<strong>al</strong> argument to the<br />

:type option) can be used as a option. This is mostly for compatibility with the old Lisp Machine<br />

defstruct. It <strong>al</strong>lows you to say just type when you should be saying (:type type). Use of this<br />

feature in new code is discouraged. It is an error to give an argument to a type used as an<br />

option in this m,tnner.<br />

MC:NII.MAN:DEFSTR 91<br />

23·IJEC-S3<br />

, ,r • ~ ~ ~ • ~ _ ... ' ~;::. ~ _ . ~ ~ "t' ~ ~ ~ _<br />

, .' •• '


-<br />

NIl. Manu<strong>al</strong> 137 The defstruct-descriplion Structure<br />

16.4.22 Other Options<br />

Fin<strong>al</strong>ly, if an option isn't found among those listed above, defstruct checks the property list<br />

of the name of the option to see if it has a non-null :defstruct-option property. If is docs have<br />

such a property. then if the option was of the fonn (optiOlrname v<strong>al</strong>ue). it is treated just like<br />

(:property option-name v<strong>al</strong>ue). That is. the defstruct is given an option-name property of v<strong>al</strong>ue.<br />

If such an option is used without an argument. it is treated just like (:property op/ion-name t).<br />

That is. it is treated as if the argument was t.<br />

'Illis provides a primitive way for the user to define his own options to defstruct. Severa} of<br />

the options listed ahove are actu<strong>al</strong>ly imp1cmel1lcd using this mechanism.<br />

16.5 The defstruct-description Structure<br />

This section discusses the intern<strong>al</strong> structures used by defstruct that might be useful to<br />

programs that want to interface to defstruct nicely. The infonnation in this section is <strong>al</strong>so<br />

necessary for anyone who is thinking of defining his own structure types (section F.6, page 138).<br />

l.isp Machine and 'II programmers will find that the symbols found only in this section arc <strong>al</strong>l<br />

interned in the "systems-intern<strong>al</strong>s" package ("51" for short).<br />

Whenever the user defines a new structure using defstruct. defstruct creates an instance of<br />

the defstruct-description structure. This structure can be found as the defstruct-description<br />

property of the name of the structure: it contains such useful infonnation as the name of the<br />

structure. the number of slots in the stnlcture. <strong>et</strong>c.<br />

The defstruct-description structure is defined som<strong>et</strong>hing like this: (This is a bowdlerized<br />

version of the re<strong>al</strong> thing, I have left out a lot of things you don't need to know un1ess you are<br />

actu<strong>al</strong>ly reading the code.)<br />

(defstruct (defstruct-description<br />

(:default-pointer description)<br />

(:conc-name defstruct-description-»<br />

name<br />

size<br />

property-<strong>al</strong>ist<br />

slot-<strong>al</strong>ist)<br />

The name slot contains the symbol supplied by the user to be the name of his structure.<br />

som<strong>et</strong>hing like spaceship or phone-book-entry.<br />

The size slot contains the tot<strong>al</strong> number of slots in an instance of this kind of structure. This<br />

is not the same number as that obtained from the :size-symbol or :size-macro options to<br />

defstruct. A named structure. for example~ usu<strong>al</strong>ly uses up an extra location to store the name<br />

of the structure. so the :size-macro option will g<strong>et</strong> a number one larger than that stored in the<br />

defstruct description.<br />

Pille property-<strong>al</strong>ist slot contains an <strong>al</strong>ist with pairs of the fonn (properly-name. properly)<br />

containing properties placed there by the :property option to defstruct or by property names used<br />

as options to defstruct (see section 16.4.20, page 136. and section 16.4.22, page 137).<br />

MC:<strong>NIL</strong>MAN:DEFSTR 91<br />

23-DFC-83<br />

.<br />

.' . .•<br />

"<br />

.~.~~ .:.·':·::·.F·c· ........<br />

. ..•... .' .'


Extensions to defstruct 138 <strong>NIL</strong> Manu<strong>al</strong><br />

The sfot-aiist slot contains an <strong>al</strong>is( of pairs of the fimn (slot-name. slot-description). A slot·<br />

descripliol1 is an ins~lnce of the defstruct-slot-description structure. The defstruct-slotdescription<br />

structure is defined som<strong>et</strong>hing like this: (another bowdlerized defstruct)<br />

(defstruct (defstruct-slot-description<br />

(:default-pointer slot-description)<br />

(:conc-name defstruct-slot-description-»<br />

number<br />

ppss<br />

init-code<br />

ref-macro-name)<br />

The number slot contains the number of the location of this slot in an instance of the<br />

structure. l.ocations arc numhered starting with O. and continuing lip to one less than the size of<br />

the structure. The actu<strong>al</strong> location of Ule slot is d<strong>et</strong>ennined by the reference c(lnsing code<br />

associated with ule type of the structure. See scction16.6. page 138.<br />

The ppss slot contains the 'byte specifkr cod~ for this slot if this slot is ~ byte field of its<br />

Jocation. If this slot is the entire location. then the ppss slot contains nil.<br />

The init-code slot contains the initi<strong>al</strong>ization code supplied for this slot by the lIser in his<br />

defstruct form. If there is no initi<strong>al</strong>ization code for this slot then the init-code slot contains the<br />

symbol %%defstruct-empty%%.<br />

Thl' r~f-rn~('r(\-narn~ ~~(\t ('(\ntains th~ sym1)(\! lllat is d('fin('d as an nccessor t.~Jt references<br />

this ,slot.<br />

16.6 Extensions to defstruct<br />

da1struct-d<strong>et</strong>1ne-typ.<br />

The macro defstruct-define-typeean be used to teach defstructabout new types itean<br />

use to implement structures.<br />

16.6.1 A Simple Example<br />

L<strong>et</strong> us start by examining a sample c<strong>al</strong>l to defstruct-define-type. This is how the :list type<br />

of structure might have been· defined:<br />

{defstruct-define-type :11st<br />

(:cons (initi<strong>al</strong>ization-list description keyword-options)<br />

:list<br />

(cons -list initi<strong>al</strong>ization-list»<br />

(:ref (slot-number description argument)<br />

(list 'nth slot-number argument»)<br />

This is the minim<strong>al</strong> example. We have provided defstruct with two pieces of code. one for<br />

cnnsing up fonns to constnJct instances of the structure. the other to cons up fonns to reference<br />

various clements of the structure.<br />

1\1C:NII.MAN:DEFSTR 91<br />

23-DEC-83


".<br />

NIl. M~mll<strong>al</strong> 139 Extensions to defstruct<br />

From the example we can see that the constructor c


Extensions to defstruct 140 <strong>NIL</strong> Manu<strong>al</strong><br />

The symbol i"ils will be bound to the code that the C(}n~tnlctor conser should use to initi<strong>al</strong>ize<br />

the slots of the structure. The exact form of this argument is d<strong>et</strong>cnnincd by the symbol kind.<br />

There arc currently two kinds of initi<strong>al</strong>ization. There is the :Iist kind, where illilS is bound to a<br />

list of initi<strong>al</strong>izations. in the correct order. with nils in uniniti<strong>al</strong>ized slots. And there is the :<strong>al</strong>ist<br />

kind. where illils is bound to an aJist with pairs of the form (s/ot-number . illit-code).<br />

111e symbol description will be bound to the instance of the defstruct-description structure<br />

(section 16.5. page 137) that defstruct maintains for this particular structure. This is so that the<br />

constructor conser can find out such things as the tot<strong>al</strong> size of the structure it is supposed to<br />

create.<br />

The symhol k(l'tnmls will be bound (() ,1 <strong>al</strong>istwith pairs of the foml (kr.l'""orc/. v<strong>al</strong>ue).<br />

where each kr,l'u:ord was a keyword supplied to the constructor macro that wasn't the name of a<br />

slot. "no r<strong>al</strong>l/r waslhe "code" Ul<strong>al</strong> followed the keyword. (Sec section 16.6.3.6. page 142. and<br />

section 16.4.2. page 128.)<br />

It is an error not to supply the :cons option to ~efstruct-define-type.<br />

16.6.3.2 :ref<br />

111C :ref option to defstruct-define-type is how the user supplies defstruct with the<br />

nccessary code that it needs to cons up a form that will reference an instance of a stnJcture of<br />

this type.<br />

The :ref option has the syntax:<br />

( : ref (number description arg-J ••. argon)<br />

body)<br />

body is some code that should construct and r<strong>et</strong>urn a piece of code that will reference an<br />

instance of a structure of this type.<br />

The symbol Ilumber will bc bound to the location of the slot that the is to be referenced.<br />

This is the same number that is found in the number slot of the defstruct-slot-description<br />

structure {section 16.5, page 137}.<br />

The symbol description will be bound to the instance of the defstruct-description structure<br />

that defstruct maintains for this particular structure.<br />

The symbols arg-i are bound to the ·fonns supplied to the accessor as arguments. Nonn<strong>al</strong>ly<br />

there should be only onc of these. The /asl argument is the one that will be defaulted by the<br />

:default-pointer option (section 16.4.7. page 132). defstruct will check that the user has supplied<br />

exactly n arguments to the accessor macro before c<strong>al</strong>ling the reference con sing code.<br />

It is an error not to supply the :ref option to defstruct-define-type.<br />

MC:NII.MAN:IJEfSTR 91<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 141 Extensions to defstruct<br />

16.6.3.3 :prcdicate<br />

The :predicate option to defstruct-define-type is how defstruct is told how to produce<br />

predicates for a particular type when the :predicate option to defstruct is used (section 16.4.5.<br />

page 131). Its syntax is:<br />

{ : p red i c ate (description name)<br />

body)<br />

The variable description will be bound to the defstruct-description structure maintained for<br />

the structure we are to generate a predicate for. The variable name is bound to the symhol that<br />

is to he defined as a predicate. b(}{~l' is a piece of code to ev<strong>al</strong>uate to r<strong>et</strong>urn the defining fonn<br />

f()r the predicate. 1\ lypic<strong>al</strong> lise of this option might look like:<br />

(:predicate (description name)<br />

'(defun ,name (x)<br />

(and (frobbozp x)<br />

(eq (frobbozref x 0)<br />

'.(defstruct-description-name»»)<br />

16.6.3.4 :olcrhcad<br />

The :overhead option to defstruct -define-type is how the user declares to defstruct that the<br />

implementation of this particular type of stnlcture "uses up" some number of slots locations in the<br />

ob.ieer actu<strong>al</strong>ly constntcted. This option is used hy variolJs "nllmeo" typcl\ of "trtl('tlJr('~ thM ~t(lre<br />

the name of the stnlcture in one location.<br />

The syntax of :overhead is:<br />

(:overhead n)<br />

where II is a fixnum that says how many locations of overhead this type needs.<br />

This number is only used by the :size-macro and :size-symbol options to defstruct. (See<br />

section 16.4.15, page 135, and section 16.4.14, page 135.)<br />

16.6.3.5 :named<br />

The :named option to defstruct-define-type controls the use of the :named option to<br />

defstruct.. With no argument the :named option means that this type is an acceptable "named<br />

structure". With an argument. as in (:named typl'"" name). the symbol type-name should be that<br />

name of some other structure type that defstruct should use if someone asks for the named<br />

version of this type. (For example, in the definition of the :list type the :named option is used<br />

like this: (:named :named-list).)<br />

MC:NII.MAN:DEFSTR 91<br />

23-DEC-83<br />

• • ... ..' _ • ~\ ' ,,~ ... ~ • r. • .,<br />

.. ~ ~ ~ • 'I.<br />

- .<br />

~ - - "'<br />

.<br />

~<br />

..


Extensions to defstruct J42 <strong>NIL</strong> Manu<strong>al</strong><br />

16.6.3.6 :keywords<br />

"Inc :keywords option todefstruct-define-type. <strong>al</strong>10ws the user to define constructor<br />

keywords (section 16.4.2. page 128) for this type of structurc. (For example the :make-array<br />

constructor keyword for structurcs of type:array on Lisp Machines.) The syntax is:<br />

( : keywordskeyword-I •.. keyword-n)<br />

where each keYK'ord-i is a symbol that the constructor conser expects to find in the keywords <strong>al</strong>ist<br />

(section 16.6.3.1. page 139).<br />

16.6.3.7 :dcfstruct -options<br />

The :defstruct-options option to defstruct,..define-typeis similar to the :keywords option.<br />

It is used to define new options that may appear in the options part of a defstruct for a structure<br />

of this type. Its syntax is:<br />

(:defstruct-options option-I ... option-II)<br />

This defines each oplioll-j to be a option to defstruct that can he used with structures of this<br />

lype. For example. tJ1e :array defstruct type for ih~ Lisp M,tchine uses the :defstruct-options<br />

option as l(lllows:<br />

(:defstruct-options :make-array)<br />

Currently this just works by giving each option-; a non-nun :defstruct-option property (see<br />

section 16.4.22. page 137). but soon it will check to be sure that each oplioll"; is 0111y used as an<br />

oPtion with structures of this type.<br />

16.6.3.8 :derstruct<br />

The :defstruct option to defstruct-define-type <strong>al</strong>lows the. user to run some code and r<strong>et</strong>urn<br />

some fonns as pan of the expansion of the defstruct macro.<br />

The :defstruct option has the syntax:<br />

( : defstruct (description)<br />

body)<br />

body is a piece of code that will be run whenever defstruct is expanding adefstruct fonn<br />

that defines a structure of this type. The symbol description wilJ be bound to the instance of the<br />

defstruct-descriptionstructure that defstruct maintains for this particular structure.<br />

The v<strong>al</strong>ue r<strong>et</strong>urned by the :defstruct option should be a list of fonns to be included with<br />

those that the defstruct expands into. lous. if you only want to run some code at defstruct<br />

expand time. and you don't want to actu<strong>al</strong>ly output any addition<strong>al</strong> code, then you should be<br />

careful to r<strong>et</strong>urn ni1 from the code in this option.<br />

1\·1C:NI1.MAT":DEFSTR 91<br />

23-DEC-83


- ~tt D ~ ·t![tt '.' tt<br />

<strong>NIL</strong> Manu<strong>al</strong> 143 Extensions to defstruct<br />

16.6.3.9 :copier<br />

The :copier option to defstruct-define-type <strong>al</strong>lows the user to tell defstruct how to generate<br />

the copier functions required by the :copier option to defstruct (section 16.4.10, page 134)~ This<br />

option is entirely option<strong>al</strong>, because defstruct <strong>al</strong>ready has enough infonnation to write an adequate<br />

copier function for any given type given the information supplied to the :ref and :cons options to<br />

defstruct-define-type. However. it is som<strong>et</strong>imes desirable to teach defstruct a b<strong>et</strong>fer way to<br />

copy a particular type of structure.<br />

The :copier option has the syntax:<br />

( : cop i e r (descriptioll nomc)<br />

body)<br />

Similar to the :predicate option. dcscription is hound to the instance of the defstructdescription<br />

structure maint~iined for this structure, name is bound to the symbol to be dcfined~<br />

and bod)' is some code to e\'<strong>al</strong>u~lte to g<strong>et</strong> the defining fonn. For example:<br />

(:copier (description name).<br />

t(defmacro ,name (x)<br />

t(copy-frobboz .x)})<br />

16.6.3.10 :implemcntations<br />

The :implementations option to defstruct-define-type is primarily useful to the mainuliners<br />

of defstruct in keeping control of the variations in defstruct types available in different<br />

implementations. Its syntax is:<br />

( : imp 1 ementati ons arg-I .•. arg-n)<br />

'<br />

This makes the defstruct-define-type in which it appears only take effect in<br />

implementations of LISP in which (status feature arg-i) is true for at least one of the arg-i.<br />

those<br />

~1C:<strong>NIL</strong>MAN:DFFSTR 91<br />

23-DEC-83


The) .OOP Iteration Macro 144 Nil. Manu<strong>al</strong><br />

17. The LOOP Iteration Macro<br />

17. t Introduction<br />

loop is a I.JSP macro which provides a programmable iteration facility. The same loop<br />

module operates compatibly in LISP MACHJNE lJSP. MACUSP(PDP-lO and MCLTICS). and <strong>NIL</strong>. and<br />

a moderately compatible package was developed for the MDL programming environment. loop<br />

was inspired by the "FOR" facility of CLISP in INTFRL1~I); however. it is not compatible and<br />

differs in sever<strong>al</strong> deLli1s.<br />

The gener<strong>al</strong> approach is that a form introduced by the word loop generates a single program<br />

J{)OP~ into which a large vari<strong>et</strong>y of features can be incorporated. The loop consists of some<br />

initi,ltiltltion (pr%gue) code. a body which may be executed se\'cr<strong>al</strong> times. and some exit<br />

(epih,gue) code. Variables m~IY be dcchlred lnc<strong>al</strong> to tJle loop. The features arc concerned with<br />

loop variables .. deciding when to end tJle itemtion. putting user-written cude into the loop.<br />

r<strong>et</strong>urning a v<strong>et</strong>lue from the construct. and iterating a variable through various re<strong>al</strong> or virtu<strong>al</strong> s<strong>et</strong>s<br />

of v<strong>al</strong>ues.<br />

The loop fonn consists of a series of chmses. each introduced by a keyword symbol. Forms<br />

appearing in or implied by the clauses of a loop form are classed as those to be executed as<br />

initi<strong>al</strong>ization code, body code. ,Uld/or exit code: within each part of the tcmplate that loop fins<br />

in. they arc executed strictly in the order implied by the origin<strong>al</strong> composition. Thus. just as in<br />

ordinarY l.isp code. side·effects may be used. and nne piece of cnde may depend on fhllowing<br />

another filr its proper operation. This is tJ1C princip<strong>al</strong> phiJosophy difference from I~TFRLlSP'S<br />

"FOR" facility,<br />

Note that loop forms are intended to look like stylized English rather than LISP code. There<br />

is a not41bly low density of parentheses. and many of the keywords are accepted in sever<strong>al</strong><br />

synonymous fonns to <strong>al</strong>low writing of more euphonious and grammatic<strong>al</strong> English. Some find this<br />

notation verbose and distasteful, while others find it flexible and convenient. The fonner are<br />

invited to stick to do.<br />

Here are some examples to illustrate the use of loop.<br />

(defun print-elements-of-list (list-of-elements)<br />

{loop for element in list-of-elements<br />

do (print element)}}<br />

nil.<br />

The above function prints each' element in its argument. which should be· a list It r<strong>et</strong>urns<br />

MC:<strong>NIL</strong>MAN;1.00J Y rM 319<br />

23-DEC-83<br />

> ••<br />

:'. .. '-. .• ". ~>. .... .. ..::-fL~,~.L~.~:i,~:.~·,~?,~,j;~.~-4·~~-s~~r·;~ ~.}i;.,;~ .......... '.


"-4 *<br />

. f t -. . ."). "'E o - ,oW1 t < ... "*('ib*~ d . ., if' " "'ffff'. 'en-'"Q"Y' .... W· 'S " -"f' $' *7 . t' 2<br />

'm<br />

<strong>NIL</strong> Manu<strong>al</strong> 145<br />

Clauses<br />

(defun gather-a1ist-entries (list-of-pairs)<br />

(loop for pair in 1ist-of-pairs<br />

collect (car pair»).<br />

gather-<strong>al</strong>ist-entries takes an association list and r<strong>et</strong>urns a list of the "keys":<br />

(gather-<strong>al</strong>ist-entries '«faa 1 2) (bar 259) (baz») r<strong>et</strong>urns (faa bar baz).<br />

that is,<br />

(defun extract-interesting-numbers (start-v<strong>al</strong>ue end-v<strong>al</strong>ue)<br />

(loop for number from start-v<strong>al</strong>ue to end-v<strong>al</strong>ue<br />

when (interesting-p number) collect number»<br />

The ahove function takes two arguments. which should be fixnums. and r<strong>et</strong>urns a list of <strong>al</strong>l<br />

the numhers in that range (inclusive) which satisfy the predicate interesting-po<br />

,(defun find-maximum-e1ement (an-array)<br />

(loop fori from 0 below (array-dimension an-array 0)<br />

maximize (aref an-array i»)<br />

find-maximum-element r<strong>et</strong>urns the maximum of the clements of its argument. a onedimension<strong>al</strong><br />

array.<br />

(defun my-remove (object list)<br />

(loop for element in list<br />

unless (equ<strong>al</strong> object element)<br />

my-remove is like tJle COM~10N LISP function remove. utilizing the equ<strong>al</strong> predicate. (This is .<br />

like MACLISP del<strong>et</strong>e, but copies the list rather than destnlctively splicing out clements.)<br />

(defun find-frob (list)<br />

(loop for element in list<br />

when (frobp element) r<strong>et</strong>urn element<br />

fin<strong>al</strong>ly (ferror nil "No frob was found in the list -S"<br />

list»)<br />

This r<strong>et</strong>urns the first element of its list argument which satisfies the predicate frobp. If none<br />

is found, an error is generated.<br />

17.2 Clauses<br />

Intern<strong>al</strong>ly, loop constructs a prog which includes variable bindings, pre-jteration (initi<strong>al</strong>ization)<br />

code. post-iteration (exit) code, the body of the iteration. and stepping of \'ariables of iteration to<br />

. their next v<strong>al</strong>ues (which happens on every iteration after executing the body).<br />

A clause consists of the keyword symbol and any Lisp fonns and keywords which it de<strong>al</strong>s<br />

with. For example.<br />

(loop for x in 1 do (print x».<br />

contains two clauses. "for x in (car foo) It and "do (pr i nt x) ". Certain of the parte; of the<br />

clause will be described as being expressions. e.g~ (car faa) in the above. An' expression is a<br />

MC:<strong>NIL</strong>MAN:I.OOPTM 319<br />

23-DEC-83


Clauses 146 NIl. Manu<strong>al</strong><br />

single LISP form. Obviously. it must be followed immediately hy either the end of the loop fonn.<br />

or by a loop keyword. Certain clauses take what is c<strong>al</strong>led a lIIulliple expression: this may be a<br />

single LISP form. or a series of ronns implicitly co11ectcd with progn. A multiple expression is<br />

terminated by the next following atom. which is taken to be a keyword. As a gener<strong>al</strong> rule. loop<br />

clauses which utilize LISP forms de<strong>al</strong> only with single expressions. with the exception of those for<br />

which the fonns are ev<strong>al</strong>uated for effect: specific<strong>al</strong>ly. only the do, initiatty. and fin<strong>al</strong>ly Clauses<br />

<strong>al</strong>low multiple expressions.<br />

This syntax differs slightly from earHer versions of loop (which arc prohably 5tiH in use in<br />

I.lSP implementations other than J';JI). in which <strong>al</strong>l expressions were treated as multiple<br />

expressions. The reason for the change is twof(>ld: first. it common syntactic error in using loop<br />

is to accidenta)J} omit the do keyword (causing the expressions meant to be executed for effcct to<br />

h~come part of the preceding clause). Second. it is anticipated th41t loop will suppon ,Ill Itimplied<br />

do" som<strong>et</strong>ime in the future. making this omission in fact synt


<strong>NIL</strong> Manu<strong>al</strong> 147 Clauses<br />

(loop ... for y = illil then (9 x) for x = (f) ... )<br />

because. as a gener<strong>al</strong> rule. par<strong>al</strong>lel stepping has more overhead than sequenti<strong>al</strong> stepping.<br />

Similarly. the example<br />

(loop for sublist on some-list<br />

and for previcius = 'undefined then sublist<br />

· .. )<br />

which is equiv<strong>al</strong>ent to the do construct<br />

(do «sublist some-list (cdr sublist»<br />

(previous 'undefined sU9list»<br />

«null sublist) ... )<br />

... )<br />

in terms of stepping. would he h<strong>et</strong>ter written as<br />

(loop for previous = 'undefined then sub1ist<br />

for sublist on some-list<br />

· .. )<br />

When iteration driving clauses are joined· with and. if the Loken following the and is not a<br />

keyword which introduces an iterau.m driving clause. it is assumed to be the same as the keyword<br />

which introduced the most recent clause; thus. the above example showing par<strong>al</strong>lel stepping could<br />

have been written as<br />

(loop for sublist on some-list<br />

and previous = 'undefined then sublist<br />

uCl:au~c<br />

· .. )<br />

I..iac keyword ior is impiicd aftcr the and.<br />

The order of ev<strong>al</strong>uation in iteration-driving clauses is that those expressions which are only<br />

ev<strong>al</strong>uated once are ev<strong>al</strong>uated in order at the beginning of the form. during the variablc-binding<br />

phase. while those expressions which are ev<strong>al</strong>uated each time around the loop are ev<strong>al</strong>uated in<br />

order in the body.<br />

One common and simple iteration driving clause is repeat:<br />

repeat expression<br />

This ev<strong>al</strong>uates expression (during the variable binding phase), and causes the loop to<br />

iterate that many times. expression is expected to ev<strong>al</strong>uate to a fixnum. If expression<br />

ev<strong>al</strong>uates to a zero or negative result. the body code will not be executed.<br />

All remaining iteration driving clauses are subdispatches of the keyword for, which is<br />

synonomous with as. In <strong>al</strong>l of them a variable of iteration is specified. Note that, in gener<strong>al</strong>, if<br />

an iteration driving clause imp1icitly supplies an cndtest, the v<strong>al</strong>ue of this iteration variable as the<br />

loop is exited (i.e., when the epilogue code is run) is undefined. (This is discussed in more d<strong>et</strong>ail<br />

in section 17.6.)<br />

Here are <strong>al</strong>l of the vari<strong>et</strong>ies of for clauses. Option<strong>al</strong> parts are enclosed in curly brack<strong>et</strong>s. The<br />

d<strong>al</strong>a-I),prs as lIsed hcre are discussed fully in section 17.4.<br />

for \'ar {data-I)'pr} in exprl {by expr2}<br />

This iterates over each of the clements in the list exprl. If the by subclause is<br />

present, expr2 is e\'<strong>al</strong>uatcd once on entry to the loop to supply the function to be<br />

used to f<strong>et</strong>ch successive sublists. instead of cdr.<br />

MC:<strong>NIL</strong>MAN;1.00PTM 319<br />

23-DEC-83


Clauses . 148 <strong>NIL</strong> Manu<strong>al</strong><br />

for \'ar {d<strong>al</strong>a-/J'f>f'} on eXl'rl {by ('xpr2}<br />

This is like the previous for format. except that voris s<strong>et</strong> to successive sublislc; of the<br />

list instead of successive clements. Note that since var will <strong>al</strong>ways be a IisL it is' not<br />

meaningful to specify a d<strong>al</strong>a-t)'pe unless var is a deslruclurillg p<strong>al</strong>ferll, as described in<br />

the section on deslruc/uring. page 158. Note a1so that loop uses a null rather than an<br />

atom test to implement both this and the preceding clause.<br />

for var {d<strong>al</strong>a-type} = expr<br />

On each iteration. expr is ev<strong>al</strong>uated and var is s<strong>et</strong> to the result.<br />

for var {data-Iype} = exprl then expr2<br />

l'(}r is hound to e.rpr/ when the loop is entered. imd s<strong>et</strong> to ('xl'r2 (rc-e\',lluated) at <strong>al</strong>l<br />

hut the first iteration. Since exprl is e\'.tIU<strong>al</strong>ed during the binding phase. it c~mnot<br />

referenccolher iteration variables s<strong>et</strong> before il~ fur that. usc the fullowing:<br />

for \'ar {dtlld-IYfJl'} first ex!'r! then expr2<br />

This' s<strong>et</strong>s \'ar to ex})rl on the first iteration. and to ex!'r] (re"ev<strong>al</strong>uated) on each<br />

succeeding iteration. The ev<strong>al</strong>uation of both expressions is . perfonned inside of the<br />

loop binding environment. befl)re the loo'p body. This <strong>al</strong>lows the first v<strong>al</strong>ue of rar to<br />

come from the first \';tlue of some other iteration \'ariah1c. <strong>al</strong>lowing such constructs as<br />

(loop for term in poly<br />

for ans first (car term)<br />

then (gcd ans (car term»<br />

fin<strong>al</strong>ly (r<strong>et</strong>urn ans»<br />

for r,;r (41&1:.; iypt) fiOin [xprl {to cxpr2} {by r..i.jlrJ)<br />

This perfonns numeric iteration. var is initj<strong>al</strong>ized to exp,l. and un each succeeding<br />

iteration is incremented by expr3 (default 1). If the to phrase is given. the iteration'<br />

tenninates whenvar becomes greater than expr2. Each of the expressions is eva1uated<br />

only oncc. and the to and by phrases may be written in either order. downto may<br />

be used instead of to. in which case var is decremented by the step v<strong>al</strong>ue, and the<br />

endtest is adjusted accordingly. If below is used instead of to. or above instead of<br />

downto, the iteration will be tenninatcd before expr2 is reached, rather than after.<br />

Note that the to variant appropriate for the direction of stepping must be used for the<br />

endtesr to be fonned corrcctly; i.e. tbec04c will not work if expr3 is negative or<br />

zero. If no limit-specifying clause is gi\'cn~then the direction of the stepping may be<br />

specified as being decreasing by using downfrom instead of from. upfrom may <strong>al</strong>so<br />

be used instead of from; it forces· the stepping direction to be increasing. The datatype<br />

defaults to fixnum. Thus. the idiom for stcpping through a typic<strong>al</strong> COMMON USP<br />

stan/end range in which the stan is inclusive and the end is exclusive, is<br />

for var from SlaTt below end<br />

for var {dat~type} being exprand its path ...<br />

for var {da/a-type} being {eachlthe} path ...<br />

This provides a user-definable iteration fhcility. path names the manner in which the<br />

iteration is to be pcrfonned. The ellipsis indicates where various path dependent<br />

preposition/expression pairs may appear. See the section on Iteration Paths (page 161)<br />

for compl<strong>et</strong>e documentation~<br />

MC:NII.MAN:LOOPTM 319<br />

23-DEC-83


¢; r .•<br />

COf . 1*& t - un ,'hrag-- trw $ - .? Wf n' -. Xt - Sfb'(¥#t&trlttiif


Clauses 150 <strong>NIL</strong> Manwtl<br />

For binding more than one variable with no panicular initi<strong>al</strong>ization. one may usc the<br />

construct<br />

with variable-list {d<strong>al</strong>a-type-list} {and ...}<br />

as in<br />

with (i j k tt t2) (fixnum fixnum fixnurn)<br />

A slightly shorter way of writing this is<br />

with (1 j k) fixnum and (tl t2) ...<br />

These arc cases of deslru!'turillg which loop handles speci<strong>al</strong>1y; destructuring and data type<br />

keywords are discussed in· sections 17.5 and 17.4.<br />

Occasion<strong>al</strong>ly there are various implementationa] reasuns for a \'ariable 1101 to be given a loc<strong>al</strong><br />

type declar4ltioll. I f this is necessclry. the nodeclare clause may be used:<br />

nodecfare rariubie-lisl<br />

"111e variables in variable-iisl are noted by loop as not requiring loc<strong>al</strong> type declarations~<br />

Consider the following: .<br />

(declare (speci<strong>al</strong> k) (fixnum k»<br />

(defun foo (1)<br />

(loop for x in 1 as k fixnum = (f x) ... »<br />

J f k did not have the 1ixnum data-type keyword given for it. then loop would bind it<br />

to nil. and some compilers would complain. On the other hand. the fixnum keyword<br />

<strong>al</strong>so produces a loc<strong>al</strong> fixnum declaration filr k: since k is speci<strong>al</strong>. some compilers will<br />

complain (or error out). The solution is to do:<br />

(defun foo (l)<br />

(loop nodeclare (k)<br />

for x in 1 as k fixnum = (f x) ... »<br />

which tells loop not to make that loc<strong>al</strong> declaration. The nodeclare clause must come<br />

before any reference to the variables so noted. Positioning it incorrectly will cause this<br />

clause 10 not take effect. and may not be diagnosed. It happens that this clause was<br />

introduced due to some peculiar behavior of the MULTICS MACLISP compiler, and<br />

should not be needed in other implementations.<br />

17.2.3 Entrance and Exit<br />

initi<strong>al</strong>ly multiple-expression<br />

This puts 11lUllipie-expression into the prologue of the iteration. It will be ev<strong>al</strong>uated<br />

before any other initi<strong>al</strong>ization code other than the initi<strong>al</strong> bindings. For the sake of<br />

good style, the initi<strong>al</strong>ly dause should therefore be placed after any with clauses· but<br />

before the main body of the loop. initi<strong>al</strong>ly is one of the few loop clauses which are<br />

<strong>al</strong>lowed to be followed by multiple expressions; these expressions will be treated as an<br />

implicit progn.<br />

finaUy multiple-expression<br />

Ibis puts multiple-expression into the epilogue of the loop, which is ev<strong>al</strong>uated when<br />

the iteration terminates (other than by an explicit r<strong>et</strong>urn). For stylistic reasons. then,<br />

this clause should appear last in the loop body. Note that cenain clauses may<br />

generate code which tenninatcs the iteration without nmning the epilogue code; this<br />

behavior is noted with those clauses. Most nowble of these are those described in the<br />

section 17.2.7. Aggregated Boolean Tests. This clause may be used to cause the loop<br />

MC:<strong>NIL</strong>MAN:1.00PTM 319<br />

23-DEC-83


JJ.''-''ilitllll·'·''I· .'·<br />

t<br />

.. Il··T.t.r·.·<br />

.n.rr.t<br />

t<br />

...,.


Clauses 152 Nil. Manu<strong>al</strong><br />

cortecting ...<br />

This causes the v<strong>al</strong>ues of expr un each iteration to be collected into a list.<br />

nconc expr {into var}<br />

nconcing ...<br />

append ...<br />

appending ...<br />

These are likecoltect. but the results are spliced tog<strong>et</strong>her.<br />

(loop for i from 1 to 3<br />

nconc(list i (. i i»)<br />

=> (1 1 2 4 3 9)<br />

The diflercnce is that. for nconc. the v<strong>al</strong>ue of ('xpris not copied oefore heing<br />

spliced. not that the entire list being accumulated is repeatedly cop ted during the<br />

iteration. This is significant in that one m,lyg<strong>et</strong> ahold of the intennediate result while<br />

the iteration is in progress by use of into, and lit<strong>al</strong> list does g<strong>et</strong> destructire!y modified.<br />

count expr {into "or} {data-type}<br />

counting ...<br />

If expr ev<strong>al</strong>uates non-nit a counter is incremented. The data-t)'p(' defaults to fixnum.<br />

sum (').pr {d<strong>al</strong>a-type} {into lIar)<br />

summing ...<br />

Ev<strong>al</strong>uates expr on each iteration. and accumulates the sum of aU the v<strong>al</strong>ues. dnla-t),pe<br />

defaults to number. which for <strong>al</strong>l practic<strong>al</strong> purposes is notype. Note that specifying<br />

d<strong>al</strong>a-l),pe implies that both the sum and the number being summed (the v<strong>al</strong>ue of<br />

expr) will be of thattypc.<br />

maximize expr {d<strong>al</strong>a-t)pe} {into var)<br />

minimize ...<br />

Computes the maximum (or minimum) of expr over <strong>al</strong>l iterations. data-type defaults<br />

to number. Note that if the loop iterates zero times, or if condition<strong>al</strong>ization prevents<br />

the code of this clause from being executed, the result will be meaningless. loop may<br />

choose to code the max or min operation itself by just using arithm<strong>et</strong>ic comparison<br />

rather than c<strong>al</strong>ling max or min, if it deems this to be reasonable based on the<br />

particular LISP implementation and the declared type of the accumulation. As with the<br />

sum clause, specifying data-type implies that both the result of the max or min<br />

operation and the v<strong>al</strong>ue being maximized or minimized will be of that type.<br />

Not only may there be multiple accumulations in a loop, but a single accumulation may come<br />

from multiple places within the same loop Jonn. Obviously, the types of the collection must be<br />

compatible. collect. nconc, and append may <strong>al</strong>l be mixed. as may sum and count, and<br />

maximize and minimize. For example,<br />

(loop for x in '(a b c) for y in '«(1 2) (3 4) (5 6»<br />

collect x<br />

append y)<br />

=> (a 1 2 b 3 4 c 5 6)<br />

MC:<strong>NIL</strong>MAN:I.OOPTM 319


<strong>NIL</strong> Manu<strong>al</strong> 153<br />

Clauses<br />

'Inc following computes the average of the entries in the list list-offrobs:<br />

(loop for x in list-of-frobs<br />

count t into count-var<br />

sum x into sum-var<br />

fin<strong>al</strong>ly (r<strong>et</strong>urn (quotient sum-var count-var»)<br />

17.2.6 Endtests<br />

The following clauses may be used to provide addition<strong>al</strong> control over when the iteration g<strong>et</strong>s<br />

lennin<strong>al</strong>ed. possihly causing exit code (due to fin<strong>al</strong>ly) to be perfonned and possihly r<strong>et</strong>urning a<br />

v<strong>al</strong>ue (e.g.. from collect).<br />

while expr<br />

If expr ev<strong>al</strong>uates to nil. the loop is exited. performing exit code (if any). and<br />

r<strong>et</strong>urning any accumulated v<strong>al</strong>ue. The test is placed in the body of the loop where it<br />

is written. It may appear b<strong>et</strong>ween sequenti<strong>al</strong> for clauses.<br />

until expr<br />

Identic<strong>al</strong> to while (not e:rpr).<br />

This may be needed. for example. to step through a strange data structure, as in<br />

(loop for concept = expr then (superior-concept concept)<br />

until (top-of-concept-tree? concept)<br />

... )<br />

lne following may <strong>al</strong>so be of usc in terminating the iteration:<br />

loop-finish<br />

(loop-finish) causes the iteration to terminate "norm<strong>al</strong>ly", the same as implicit tcnnination<br />

by an iteration driving clause, or by the use of while or until-the epilogue code (if any)<br />

will be run. and any implicitly collected result will be r<strong>et</strong>urned as the v<strong>al</strong>ue of the loop.<br />

For example.<br />

(loop for x in '(1 2 3 4 5 6)<br />

collect x<br />

do (cond «= x 4) (loop-finish»»<br />

=> (1 2 3 4)<br />

This particular example would be b<strong>et</strong>ter written as until (= x 4) in place of the do<br />

clause. Also. the readability of loop constructs suffers from the inclusion of a nonkeyword<br />

construct which affects the behavior of the iteration because the reader of the<br />

code may not be expecting it hidden away in the code. (Stylistic<strong>al</strong>ly it might be<br />

compared with the use of go.)<br />

MC:NI1.MAN:LOOPTM 319<br />

23-I)EC-83


Cl.IUSCS 154 Nil. Manu<strong>al</strong><br />

17.2.7 Aggregated Boolean Tests<br />

All of these clauses pcrfonn some test.<br />

depending on the result of that test.<br />

and may immediately tcnninatc the iteration<br />

aJways expr<br />

Causes the loop to r<strong>et</strong>urn t if expr <strong>al</strong>ways ev<strong>al</strong>uates non-null. If expr ev<strong>al</strong>uates to nil.<br />

the loop immediately r<strong>et</strong>urns nil. without running the epilogue cod,c (if any. as<br />

specified with the fin<strong>al</strong>ly clause): otherwise, t will bc r<strong>et</strong>urned when the loop finishes.<br />

after the epilogue code has been run.<br />

never {'xpr<br />

Causes the loop to r<strong>et</strong>urn t if l'xpr never e"<strong>al</strong>u.ltes non-null. This is equiv<strong>al</strong>ent to<br />

<strong>al</strong>ways (not ('xpr).<br />

thereis expr<br />

If rxpr cv<strong>al</strong>uates non-nil. then thc iteration is tenninatcd and that v<strong>al</strong>ue is r<strong>et</strong>urned.<br />

without running the epiloguc code.<br />

17.2.8 ('ondition<strong>al</strong>ization<br />

These clauses may be used to tfcondition<strong>al</strong>ize" the following clause. They may precede any of<br />

the side-effecting or v<strong>al</strong>ue-producing clauses. such as do. collect. <strong>al</strong>ways, Of r<strong>et</strong>urn.<br />

when expr<br />

if expr<br />

If expr ev<strong>al</strong>uates to nil. the following clause will be skipped. otherwise not.<br />

unless expr<br />

This is equiv<strong>al</strong>ent to when (not expr».<br />

1\.1ultiplc condition<strong>al</strong>ization c1auscs may appear in sequence. If one test fails, then any<br />

following tests in the immediate sequence, and the clause being condition<strong>al</strong>ized, arc skipped. For<br />

instance,<br />

(loop for x ...<br />

when (f x)<br />

unless (g x)<br />

do ••• )<br />

is like<br />

(loop for x •.•<br />

when (and (f x) (not (g x»)<br />

do ••• )<br />

Multiple clauses may be condition<strong>al</strong>ilcd under the same test by joining them with and, as in<br />

(loop fori from a to b<br />

when (zerop (remainder; 3»<br />

collect i and do (pr;nt i»<br />

which r<strong>et</strong>urns a list of <strong>al</strong>l mUltiples of 3 from a to b (inclusive) and prints them as they are<br />

being collected.<br />

~1C:NII.M!\N:1.00PTM 319<br />

23-DEC-83


t<br />

, I<br />

I<br />

I<br />

!<br />

I<br />

<strong>NIL</strong> Manu<strong>al</strong> 155<br />

Clauses<br />

If-then-else condition<strong>al</strong>s may be written using the else keyword. as in<br />

(loop for i from a to b<br />

when (oddp i)<br />

collect i into odd-numbers<br />

else collect i into even-numbers)<br />

Multiple clauses may appear in an else-phrase. using and to join them in the same way as above.<br />

There is a bug ill the handling of multiple else clauses. Beware.<br />

Condition<strong>al</strong>s may be nested. For example.<br />

(loop fori from a to b<br />

when (zerop (remainder i 3})<br />

do (print i)<br />

and when (zerop (remainder i 2»<br />

collect i)<br />

r<strong>et</strong>urns a list of <strong>al</strong>l multiples of 6 from a to b. and prints <strong>al</strong>l multiples of 3 from a to b.<br />

When else is llsed with nested condithm<strong>al</strong>s. the "dangling else" ambiguity is resolved by<br />

matching the else with the innennost when not <strong>al</strong>ready matched with an else. Here is a<br />

complicated example.<br />

(loop for x in 1<br />

when (atom x)<br />

when (memq x *distingu;shed-symbols*)<br />

do (processl x)<br />

~lse do (proc~ssZ x)<br />

elsa when (memq (car x) *speci<strong>al</strong>-prefixes*)<br />

collect (process3 (car x) (cdr x»<br />

and do (memoize x)<br />

else do (process4 x})<br />

Useful with the condition<strong>al</strong>ization clauses is the r<strong>et</strong>urn clause. which causes an explicit r<strong>et</strong>urn<br />

of its "argument" as the v<strong>al</strong>ue of the iteration, bypassing any epilogue code. That is,<br />

when exprl r<strong>et</strong>urn expr2<br />

is equiv<strong>al</strong>ent to<br />

when exprl do (r<strong>et</strong>urn expr2)<br />

if the loop is not "named" (by use of the named clause), and to<br />

when exprl do (r<strong>et</strong>urn -from name expr2)<br />

jf the loop is named name. In other words, r<strong>et</strong>urn arranges to <strong>al</strong>ways r<strong>et</strong>urn from the loop it is<br />

a part of.<br />

Condition<strong>al</strong>ization of one of the "aggregated boolean v<strong>al</strong>ue" clauses simply causes the test<br />

which would cause the iteration to tenninate early not to be performed unless the condition<br />

succeeds. For example.<br />

(loop for x in 1<br />

when (significant-p x)<br />

do (print x) (princ "is significant.")<br />

and thereis (ext~a-speci<strong>al</strong>-significant-p x»<br />

does not make the extra-speci<strong>al</strong>-significant-p check unless the significant-p check succeeds.<br />

MC:<strong>NIL</strong>MAN:1.00PTM 319<br />

23-DEC-83


Clauses 156 NIl. Manu<strong>al</strong><br />

The fonn<strong>al</strong> of a conditionaJized clause is typic<strong>al</strong>ly som<strong>et</strong>hing like<br />

when ('xprl k('yword exprl<br />

Ifexpr2 is the keyword it~ then a variable is generated to hold the v<strong>al</strong>ue of exprl. and that<br />

variable g<strong>et</strong>s substituted for exprl. Thus, the composition<br />

when exprr<strong>et</strong>urn it<br />

is equiv<strong>al</strong>ent to the c1ause<br />

thereis expr<br />

and one may coBect <strong>al</strong>l non-nuH v<strong>al</strong>ues in an iteration by saying<br />

when (':rpr('ssioll collect it<br />

If multiple clauses arc joined with and. the it keyword m,l), only be lIsed in the first. If multiple<br />

whens. unless('s. and/or ifs occur in sequence. the \'<strong>al</strong>ue suhstituled for it will he thilt of the last<br />

tl'Sl perf(mncd. The it keyword is not rccogni/ed in an else-phmsc.<br />

17.2.9 l\1isceUaneous Other ('Iauses<br />

named n<strong>al</strong>11(,<br />

This gives the block (prog) which loop generates a name of name, so that one may<br />

usc the r<strong>et</strong>urn-from fonn lo r<strong>et</strong>urn explicitly out of th<strong>al</strong> particular loop:<br />

(loop named sue<br />

do (loop ... do (r<strong>et</strong>urn-from sue v<strong>al</strong>ue) 0 00 )<br />

... )<br />

1'h(' r<strong>et</strong>urn -from fnnn ~h(n."n C~!.!$CS va!::[' to b~ !mmcdiat~!y rcturn~d a5 :..~c v<strong>al</strong>ue of<br />

the otHer loop. Only one name may be given to any particular loop constmct. This<br />

feature docs not exist in the MACLlSI' version of loop. since MACUSP docs nol suppon<br />

"named progs" or COMMOl" LISP ,blocks.<br />

r<strong>et</strong>urn expression<br />

Immediately r<strong>et</strong>urns the v<strong>al</strong>ue of expression as the v<strong>al</strong>ue of the loop~ without running<br />

the epilogue code. This is most useful with. some son of conditionaJization. as<br />

discussed in the previous section. Unlike most of the other clauses, r<strong>et</strong>urn is not<br />

considered to "generate body code'\ so it is <strong>al</strong>lowed to occur b<strong>et</strong>ween iteration<br />

clauses. as in<br />

(loop for entry in list<br />

when (not (numberp entry»<br />

r<strong>et</strong>urn (errol" ..• )<br />

as frob = (times entry 2)<br />

... )<br />

If one instead desires the loop to have some r<strong>et</strong>urn v<strong>al</strong>ue when it finishes nonn<strong>al</strong>ly t<br />

one may place a ca11 to r<strong>et</strong>um or r<strong>et</strong>urn-from (as appropriate) in the epilogue (with<br />

the fin<strong>al</strong>ly clause. page 150). r<strong>et</strong>urn <strong>al</strong>ways r<strong>et</strong>urns from the loop it is a pan of; that<br />

is, it turns into a c<strong>al</strong>l to r<strong>et</strong>urn if the loop is not "named", r<strong>et</strong>urn-from if it is.<br />

MC:NII.MAN:LOOPTM 319<br />

23-DEC-83


--<br />

N ll. Manu<strong>al</strong> 157 I.oop Synonyms<br />

17.3 Loop Synonyms<br />

define-loop-macro keyword<br />

May be used to make keyword. a loop keyword (such as for). into a Lisp macro which<br />

may introduce a loop form. For example. after ev<strong>al</strong>uating<br />

(define-loop-macro for),<br />

one may now write an iteration as<br />

(for; from 1 below n do ... )<br />

This facility exists primarily for diehard users of a predecessor of loop. Its unconstrained usc<br />

is not recommended. as it tends to dCl'rease the transportahility of the code and needlessly uses<br />

up ~I function n


Dcstructuring 158 Nil. MJnu<strong>al</strong><br />

number<br />

notype<br />

Any number.<br />

Unspecified type (i.e.. anything else). This name is inherited from MACLISP.<br />

Note that explicit specification of a non-numcric type for an operation which is numeric (such<br />

as the summing clause) may cause a variable to be initi<strong>al</strong>izcd to nil when it should be O.<br />

If loc<strong>al</strong> data-type declarations must be inhibited. one can usc the nodecfare clause. which is<br />

described on page 150.<br />

17.5 Dcstructuring<br />

IJrstrucluring provides one with the ability tu "simultaneollsly" assign or bind multiple<br />

v(lriablcs to components of some data structure. Typic<strong>al</strong>ly this is used with list stnJcture. For<br />

example,<br />

h~ls<br />

(loop with 1foo . bar) = 'ea b c) .. 0)<br />

the effect of binding foo to a and bar to (b c).<br />

loop's destructuring support is intendcd to par<strong>al</strong>lel if not augment that provided by the hust<br />

LISP implementation. with a go<strong>al</strong> of minim<strong>al</strong>ly providing destructuring over Jist structure patterns.<br />

Thus, in I -isp implementations with no system dcstructuring support at <strong>al</strong>l. one may still usc liststructure<br />

patterns as loop iteration variables, and in with bindings. In <strong>NIL</strong>, loop <strong>al</strong>so supports<br />

dcstrucIUring over vectors (they should be gener<strong>al</strong> vecto~ Le .. have element-typ<strong>et</strong>).<br />

One may specify the data types of the components of a pattern by using a corresponding<br />

pattern of the data type keywords in place of a single data type keyword. This syntax remains'<br />

unambiguous because whcrever a data type keyword is possible. a loop keyword is the only other<br />

possibility. Thus. if one wants to do<br />

(loop for x in 1<br />

as i fixnum = (car x)<br />

and j fixnum = (cadr x)<br />

and Ie fixnum = (cddr x)<br />

•• 0 )<br />

and no reference to x is needed, one may instead write<br />

(loop for (i j . Ie) (fixnum fixnum . fixnum) ;n 1 ••• )<br />

To <strong>al</strong>low some abbreviation of the data. type pattern, an atomic component of the data type<br />

pattern is considered to state that <strong>al</strong>l components of the corresponding part of the variable pattern<br />

are of that type. That is, the previous form could be written as<br />

( 1 00 p for (i j . Ie) fix n urn i n 1 • 0 • )<br />

This gener<strong>al</strong>ity <strong>al</strong>lows binding of multiple typed variables in a reasonably concise manner, as in<br />

(loop with {a b c) and (i j k) fixnum .. 0)<br />

which binds a. b, and c to nil and i. j. and k to 0 for use as temporaries during the iteration.<br />

and declares i .. j, and k to be fixnums for the benefit of the compiler.<br />

MC:NII.MAN~LOOPTM 319<br />

23·DEC·83


NIl. Manu<strong>al</strong> 159<br />

The Iteration Framework<br />

(defun print-with-commas (list)<br />

(loop for (item. more?) on list<br />

do (princ item)<br />

when more? do (prine ". H»~)<br />

wi1l generate the output<br />

Foo, Bar. Baz<br />

when c<strong>al</strong>led on the list ("Faa" "Bar" ttBaz").<br />

In I.lSP implementations where loop perfonns its own destrucluring. notably MUITlCS MACUS}><br />

and IISP ~1ACIII'I: liSP. one can cause loop to liSt' <strong>al</strong>ready prodded destrllcturing support<br />

instead:<br />

51: loop-u5e-5ystem-de5tru<strong>et</strong>ur1ng? Variable<br />

This variable only exists in loop implementations in LISPS which do not provide<br />

destruclllring support in the default environment. It is by default nil. If changed, then<br />

loop wi'l behave as it docs in I.lSPS which do provide dcstructuring support: destructuring<br />

binding will be pcrfi)rmed llsing l<strong>et</strong>. and destructuring assignment will be perfonned llsing<br />

des<strong>et</strong>q. Presumably if one's person<strong>al</strong>ized environment supplies these macros, then one<br />

should s<strong>et</strong> this variable to t~ there is, however, little (if any) efficiency loss if this is not<br />

done.<br />

17.6 The It£lr:ltion Framework<br />

This section describes the way loop constructs iterations. It is necessary if you will be writing<br />

your own iteration paths, and may be useful in clarifying what loop docs with its input<br />

loop considers Ille act of stepping to have four possible parts. Each iteration-driving clause<br />

has some or <strong>al</strong>l of these four parts, which are executed in this order:<br />

pre-step-endtest<br />

This is an endtest which d<strong>et</strong>ennines if it is safe to step to the next v<strong>al</strong>ue of the<br />

iteration variable.<br />

steps<br />

Variables which g<strong>et</strong> "stepped". This is intern<strong>al</strong>ly manipulated as a list of the fonn (varl<br />

v<strong>al</strong>l var2 v<strong>al</strong>2 ... ); <strong>al</strong>l of those variables arc stepped in paranel. meaning that <strong>al</strong>l of the<br />

v<strong>al</strong>s arc ev<strong>al</strong>uated before any of the vars are s<strong>et</strong><br />

post-step-endtest<br />

Som<strong>et</strong>imes you can't see if you are done until you step to the next v<strong>al</strong>ue; that is, the<br />

endtest is a function of the stepped-to v<strong>al</strong>ue.<br />

pseudo-steps<br />

Other things which need to be stepped. lbis is typic<strong>al</strong>ly used for intern<strong>al</strong> variables<br />

which arc more conveniently stepped here. or to s<strong>et</strong> up iteration variables which are<br />

functions of some intern<strong>al</strong> variablc(s) which arc actu<strong>al</strong>ly driving the iteration. This is a<br />

list like steps, but the variables in it do not g<strong>et</strong> stepped in par<strong>al</strong>lel.<br />

MC:<strong>NIL</strong>MAN:1.00PTM 319<br />

23-DEC-83


"I'he ltermion Framework . 160 <strong>NIL</strong> Manu<strong>al</strong><br />

The ahove <strong>al</strong>one is actuafly insufficient in just about <strong>al</strong>l iteration dri\ ing clauses which loop<br />

handles. What is missing is that in most cases the stepping and testing fhr the first time through<br />

the loop is different from that of aJJ other times. So. what loop de<strong>al</strong>s with is two four-tuples as<br />

above; one for the first iteration. and one fhr the rest. The first may be thought of as describing<br />

codc which immediately precedes the loop in the prog. and the second as following the body<br />

code-in fact. loop docs just. this. but severely perturbs it in order to reduce code duplication.<br />

Two lists of fonns arc constructed in par<strong>al</strong>lel: one is the first-iteration endtests and steps, the<br />

other the rcmaining,:,iterations endtests and steps. These lists have dummy entries in them so that<br />

identic<strong>al</strong> expressions will appe.lr in the scmle position in both. When loop is done parsing an of<br />

the clauses. these lists gel merged bark wg<strong>et</strong>her such that corresponding identic<strong>al</strong> expressions in<br />

hoth lists arc not duplicated unless they arc "simplc" and it is worth doing.<br />

Thus. one lIIay g<strong>et</strong> some duplicated code if one lias multiple iterations. Alternatiyely. loop<br />

may decide to usc and test a flag variable which indicates wh<strong>et</strong>her one iteration has been<br />

perfonned. In genera1. sequenti<strong>al</strong> itcrations have less (}\·crhcad th.m par<strong>al</strong>lel iterations. both from<br />

thc inhercnL overhead of stepping multiple variables in par<strong>al</strong>lel. and from thc s14mdpoint ·of<br />

potentia) code duplication.<br />

One other point which must be notcd ahout pclr<strong>al</strong>lc1 stepping is that <strong>al</strong>though thc user<br />

iteration variables arc guarantecd to be stepped in par<strong>al</strong>lcl. the placement of the endtcst for any<br />

particular iteration may bc either before Of after the stepping. A notable casc of this is<br />

(loop for i from 1 to 3 and dummy = (print 'fool<br />

collect i)<br />

_.... I.. '\ ., '\<br />

-, \.a. c. v J<br />

but prinl~ foo four times. Certain other constructs. such as for l'ar on. mayor may not do this<br />

depcnding on the particular construction.<br />

This prohlcm <strong>al</strong>so means that it may not be Stlfe to examine an iteration variable in the<br />

epilogue of the loop fonn. As a gener<strong>al</strong> rule, if an iteration driving clause implicitly supplies an<br />

endtest. then one cannot know the state of the iteration variable whcn the loop tcnninatcs.<br />

Although one can guess on the basis of wh<strong>et</strong>her the iteration variable itself holds the data upon<br />

which the endtest is based. that guess may be wrong. Thus.<br />

(loop for subl on expr<br />

fin<strong>al</strong>ly (f subl»<br />

IS Incorrect. but<br />

(loop as frob = expr whi le (g frob)<br />

fin<strong>al</strong>ly (f frob»<br />

is safe because the endtest is explicitly dissociated from the stepping.<br />

MC:NII.MAN:1.00PTM .U9<br />

23-DEC-83


.'t'fnc ; mtfrM rt'¥?9 an Tf N '" T" at' , 7thM ~'{ rt t inea@-'"<br />

;'@ rtr$v'xYtc ,""'.nV? cn -u<br />

<strong>NIL</strong> Manu<strong>al</strong> 161 Iteration Paths<br />

17.7 Iteration Paths<br />

Iteration paths provide a mechanism for user extension of iteration-driving clauses. The<br />

interface is constrained so that the definition of a path need not depend on much of the intern<strong>al</strong>s<br />

of loop. The typic<strong>al</strong> fonn of an iteration path is<br />

for var {data-type} being {eachlthe} p<strong>al</strong>hname {preposilionJ exprJ} ...<br />

pathname is an atomic symbol which is defined as a loop path function. The usage and<br />

defaulting of data-type is up to the path function. Any number of preposition/expression pairs<br />

may be present: the prepositions <strong>al</strong>lowable for any particular path are defined by that path. For<br />

example.<br />

(loop for x being the elements of some-sequence from 1 to 10<br />

· .. )<br />

To enhance readability. iteration path names are usu<strong>al</strong>ly defined in both the singular and plur<strong>al</strong><br />

fnnns: this particular example could h,lve been written as<br />

(loop for x being each element of some-sequence from 1 to 10<br />

· .. )<br />

Another fonnat. which is not so gener<strong>al</strong>ly applicable. is<br />

for l'ar{data-I),pc} being exprO and its path-name {prcposiliolll exprl} ...<br />

In this fonnat. var wkes on the v<strong>al</strong>ue of exprlJ the first time through the loop. Support for this<br />

fonnat is usu<strong>al</strong>ly limited to paths which step through some data structure. such as the "superiors"<br />

of som<strong>et</strong>hing. Thus, we can hypothesize the cdrs path, such that<br />

(loop for x being the cdrs of '(a b c . d) collect x)<br />

~; «b C . d) (c . d) d)<br />

but .<br />

(loop for x being '(a b c . d) and its cdrs collect x)<br />

=> «a be. d) (b c . d) (c . d) d}<br />

To satisfy the anthropomorphic among you, his. her. or their may be substituted for the its<br />

keyword. as may each. Egocentricity is not condoned. Some example uses of iteration paths arc<br />

shown in section 17.7.l.<br />

Very often. iteration paths step intern<strong>al</strong> variables which the user does not specify. such as an<br />

index into some data-structure. Although in most cases the user docs not wish to be concerned<br />

with such low-level matters, it is occasion<strong>al</strong>ly useful to have a handle on such things. loop<br />

provides an addition<strong>al</strong> syntax with which one may provide a variable name to be used as an<br />

"intern<strong>al</strong>" variable by an iteration path, with the using "preposition<strong>al</strong> phrase". The using phrase<br />

is placed with the other phrases associated with the path, and contains any number of<br />

keywordh ariable-name pairs:<br />

(loop for x being the elements of seq using (index i)<br />

· .. )<br />

which says that the variable i should be used to hold the index of the sequence being stepped<br />

through. The panicular keywords which may be used are defined by the iteration path; the index<br />

keyword is recognized by <strong>al</strong>l loop sequence paths (section 17.7.1.2). Note that any individu<strong>al</strong><br />

using phrase applies to only one path; it is parsed <strong>al</strong>ong with the "preposition<strong>al</strong> phrases". It is<br />

an error if the path docs not c<strong>al</strong>l for a variable using that keyword.<br />

By speci<strong>al</strong> dispensation, if a path-name is not recognized. then the default-loop-path path<br />

will be invoked upon a syntactic transfonnation of the origin<strong>al</strong> input. Essenti<strong>al</strong>ly. the loop<br />

fragment<br />

MC:NIl.MAN:I.OOPTM 319<br />

23-IJEC-83<br />

$'""}o .... ;: ••<br />

~~:- . . "~ .. ::';:;,:~~;{:i~:l~+~':«':,:,~"{tj\,' . -,


Iteration Paths<br />

162<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

for var bei ng frob<br />

is taken as if it were<br />

for var being default-loop-path in frob<br />

and<br />

for var bei ng expr and its frob •••<br />

is taken as if it were<br />

for var being expr and its default-loop-path in frob<br />

Thus, this "undefined path-name hook" only works if the default-loop-path path is defined.<br />

Ohviously. the usc of this "hook" is comp<strong>et</strong>itive. since only une such hook may be in usc, and<br />

the potenti<strong>al</strong> for syntactic amhiguity exists if frob is the name of a defined iteration path. 'Ibis<br />

feature is not f()f casu<strong>al</strong> usc: it is intended for usc by large systems which wish to usc a speci<strong>al</strong><br />

SyntilX for some fe<strong>al</strong>Ure tJley provide.<br />

17.7.1 Pre-Defined Paths<br />

loop comes with two pre-defined iteratinn pat~ functions: one implements a mapatoms-like<br />

iter.,tion path facility_ and the other is used for defining iteration paths for stepping through<br />

sequences.<br />

17.7.1.1Thc Interned-Symbols Path<br />

The interned -symbols iteration path is like amapatoms (or COMMO!\ LISP do-symbols) for<br />

loop.<br />

(loop for sym being interned-symbols ... )<br />

iterates over <strong>al</strong>l of the symbols in the current package and its superiors (or. in' Maclisp. the<br />

current obarray). This is the same s<strong>et</strong> of symbols which mapatoms iterates over, <strong>al</strong>though not<br />

necessarily in the same order. The particular package to look in may be specified as in<br />

(loop for sym being the interned-symbols in package ••• )<br />

which is like giving a second argument to mapatoms.<br />

In LISP implementations with some son of hierarchic<strong>al</strong> package structure such as USP<br />

MACHINE USP and NIl; one may restrict the iteration to be over just the package specified and<br />

not its superiors, by using the loc<strong>al</strong>-interned -symbols path:<br />

(loop for sym being the loc<strong>al</strong>-interned-symbols {in package}<br />

... )<br />

Example:<br />

(defun my-apropos {sub-string &option<strong>al</strong> (pkg package»<br />

(loop for x being the interned-symbols in pkg<br />

when (string-search sub-string x)<br />

when (or (boundp x) (fboundp x) (plist x»<br />

do (print-interesting-info x»)<br />

In the LISP MACHINE USP and <strong>NIL</strong> implementations of loop. a package specified with the in<br />

preposition may be' anything acceptahle to the pkg-find-package function. The code generated<br />

by this path will comain c<strong>al</strong>ls ((l intern<strong>al</strong> loop functions. with tJ1C CtfL'Ct that it will be transparent<br />

to changes to tJle implementation of packages. In the MACf .ISP implementation. the obarray must<br />

be an array pointer. not a symbol with an array propeny.<br />

MC:NII.Mi\N:I.OOPTM 319<br />

23-I)EC-83


<strong>NIL</strong> Manu<strong>al</strong> 163 Iteration P<strong>al</strong>lls<br />

17.7.1.2 Sequence Iteration<br />

One very common fonn of iteration is that over the c1ement~ of some object which is<br />

accessible by means of an integer index. loop defines an iteration p<strong>al</strong>ll function for doing this in<br />

a gener<strong>al</strong> way, and provides a simple interface to <strong>al</strong>low users to define iteration paths for various<br />

kinds of "indexable" data.<br />

def1ne-loop-sequence-path<br />

(def i ne-1 oop-sequence-path p<strong>al</strong>h-llame-o~lIames<br />

fe/ch-full size-full<br />

.\"('ljucllc('-Iype dcfiJu!t-wu'-type)<br />

l'olli-lIt1I11C-O""I/(//II('s is either an atomic p~tth name or list of path names. fe/ch-full is a<br />

function of two arguments: the sequence. and the index of the item to be f<strong>et</strong>ched.<br />

(Indexing is asslImed to he lero-origined.) si:c-/im is a function of one argument. the<br />

~eqllence: it should r<strong>et</strong>urn the number of clements in the sequence. sequel1ce-type is the<br />

name of the data-type of the sequence, and dljGu/t·l'a,. .. t),pe the name of the data-type of<br />

the clements of the sequence. These last two items are option<strong>al</strong>.<br />

The ~IL implementation of loup utilizes the COMMO!' LISP sequence manipulation primitives<br />

to define both element and elements as iteration paths:<br />

(define-loop-sequence-path (element elements)<br />

elt length)<br />

Then. the loop clause<br />

f',,1" .".,r nn; nn<br />

#'>",....,,, ... ,..,,,<br />

• ...,. • .... w ........ ~ the clements of .n "1"'(. III C.<br />

will step var over the clements of sequence. starting from O. The sequence p<strong>al</strong>ll function <strong>al</strong>so<br />

accepts in as a synonym for of.<br />

The range and stepping of the iteration may he specified with the use of <strong>al</strong>l of the same<br />

keywords which are accepted by the loop arithm<strong>et</strong>ic stepper (for var from ... ); they are by, to,<br />

downto. from, downfrom, below, and above, and are interpr<strong>et</strong>ed in the same manner. Thus,<br />

(loop for var be; n9 the e1 ements of sequence<br />

from 1 by 2<br />

... )<br />

steps var over <strong>al</strong>l of the odd clements of sequence, and<br />

(loop for var be; ng the el ements of sequence<br />

downto 0<br />

... )<br />

steps in "reverse" order.<br />

The <strong>NIL</strong> implementation of loop defines the following addition<strong>al</strong> sequence iteration paths.<br />

Basic<strong>al</strong>1y, they are <strong>al</strong>l speci<strong>al</strong> cases of the gener<strong>al</strong> elements path, but can generate b<strong>et</strong>ter code<br />

because they may know how to access the sequence b<strong>et</strong>ter. (If <strong>NIL</strong>'s compiler were smarter, one<br />

would be able to g<strong>et</strong> the same effect willl type declarations. but that is not the case y<strong>et</strong>.) Each<br />

iteration path name is defined in both the singular and plur<strong>al</strong> fonn.<br />

vector-elements<br />

This will iterate over any type of vector. There re<strong>al</strong>ly isn't a good reason to lise this<br />

over the elements iteration path anymore.<br />

MC:<strong>NIL</strong>MAN:1.00PTM 319<br />

23-))EC-8J


Iteration Paths<br />

164 <strong>NIL</strong> M,mu<strong>al</strong><br />

characters<br />

string -elements<br />

This iterates over the characters of a string. char is used to reference them. hence<br />

the iteration variable defaults to type string-char.<br />

bits<br />

bit - vector-elements<br />

This iterates over the bits in a bit-vector: the iteration variable is declared to be bit,<br />

as it can take on only 0 or 1 . as v<strong>al</strong>ues.<br />

The following arc the speci<strong>al</strong> cases which m~ly be of somewhat more intercst. because they<br />

can generate much bener code kl~(}wing that the sequence is of it pankular simple type:<br />

simple-vector-elements<br />

The sequence must be a simp1c lector.<br />

simple -string - elements<br />

The sequence must be a simple string.<br />

sim~: ~ - bit - vector-elements<br />

The sequence must he a simple bit vcctor.<br />

An such sequcnce iteration paths <strong>al</strong>low one to specify the variable to be used as the index<br />

variable. by use of the index keyword with the using preposition<strong>al</strong> phrase. as described ( with an<br />

example) on page 161.<br />

17.7.2 Defining Paths<br />

This section and the next may not be of interest to those not interested in defining their own<br />

iteration paths.<br />

A loop iteration clause (e.g. a for or as clause) produces. in addition to the code which<br />

defines the iteration (section 17.6), variables which must be bound~ and pre-iteration (prologue)<br />

code. This breakdown <strong>al</strong>lows a user-interfacc to loop which docs not have to depend on or know<br />

about the intern<strong>al</strong>s of loop. To compl<strong>et</strong>e this separation. the iteration path mechanism parses the<br />

clause before giving it to the user function which will r<strong>et</strong>urn those items. A function to generate<br />

code for a path may be declared to loop with the define-loop-path function:<br />

define-loop-path<br />

(dafi ne-l oop-path p<strong>al</strong>h·flame-o~names path-function<br />

Iisl-of<strong>al</strong>lowable-prepositions<br />

datum- J datum- 2 ••• )<br />

This defines p<strong>al</strong>h-/ullClioll to he the handler for the path(s) path-Ilame-or-names. which<br />

may be eithcr a symbol or a list of symbols. Such a handler should fonow the<br />

conventions described below. The datum-; are option<strong>al</strong>; they are passed in to pathfunc/ioll<br />

asa list<br />

The handler will be caned with the following arguments:<br />

path-Ilame<br />

The name ofth.e path which caused the path function to he invoked.<br />

MC:NH.MAN:OPATH 11<br />

23-DEC-83


jiiJ' ?t<br />

t m t n n 't<br />

Nil. Manu<strong>al</strong> 165 heration Paths<br />

l'ariable<br />

'1l1e "iteration variable".<br />

data-type<br />

'Ibe data type supplied with the iteration variable, or nil if none was supplied.<br />

preposition<strong>al</strong>-phrases<br />

'Ibis is a list with entries of the fonn (preposition expression). in the order in which<br />

they were collected. This may <strong>al</strong>so include some supplied implicitly (e.g. an of phrase<br />

when the iteration is inclusive. and an in phrase for the default-loop-path path): the<br />

ordering will show the order of ev<strong>al</strong>uation which should be followed for the<br />

expressions.<br />

inclusive?<br />

'Ibis is t if variable should have the starting point of the path as its v<strong>al</strong>ue on the first<br />

iteration (by virtlle of being specified with syntax like for l'elf being expr and its<br />

p<strong>al</strong>/m<strong>al</strong>lu'). nil otherwise. When t, expr will appear in prepositiun<strong>al</strong>-phrases with the<br />

of preposition: for example. for x being faa and it~i cdrs g<strong>et</strong>s preposition<strong>al</strong>-phrases<br />

of «of faa».<br />

<strong>al</strong>lowed-preposi t iOlls<br />

'1l1is is the list of <strong>al</strong>lowable prepositIOns declared for the pathname that caused the<br />

path function to be invoked. It and data (immediately below) may be used by the<br />

path function such that a single function may handle similar paths.<br />

data<br />

This is the list of "data" declared for the pathname that caused the path function to<br />

be invoked. It may. for instance. contain _ a canonic<strong>al</strong>ized pathname, or a s<strong>et</strong> of<br />

functions or flags to aid the path function in d<strong>et</strong>ermining what to do. In this way,<br />

the same path function may be able to handle different paths.<br />

The handler should r<strong>et</strong>urn a list of either six or ten clements:<br />

variable-bindings<br />

This is a list of variables which need to be bound. 'The entries in it may be of the<br />

fonn variable. (variable expression). or (variable expression data-t)pe). Note that it is<br />

the responsibility of the handler to make sure the iteration variable g<strong>et</strong>s bound. All of<br />

these variables will be bound in par<strong>al</strong>lel; if initi<strong>al</strong>ization of one depends on others. it<br />

should be done with a s<strong>et</strong>q in the prologue-fonns. R<strong>et</strong>urning only the variable<br />

without any initi<strong>al</strong>ization expression is not <strong>al</strong>lowed if the variable is a destructuring<br />

pattern.<br />

prologue-Jorms<br />

This is a list of fonns which should be included in the loop prologue.<br />

the four items of the iteratioll specification<br />

These are the four items described in section 17.6. page 159: pre-step-endtest. steps,<br />

posr-slep-endtest, and pseudo-steps.<br />

another Jour items of iteratioll specification<br />

If these four items are given. they apply to the first iteration. and the previous fOllr<br />

apply to <strong>al</strong>l succeeding iterations; otherwise, the previous four apply to <strong>al</strong>l iterations.<br />

MC:Nll.MAN:I.OOPTM 319<br />

23-DEC-83


Iter<strong>al</strong>ion Paths 166 N II. Manu<strong>al</strong><br />

Here are the routines which are used hy loop to compare keywords for equ<strong>al</strong>ity. In <strong>al</strong>l cases.<br />

a /okcll may he any LISP object. but a keytwJrdis expected to be an atomic symbol. In cerwin<br />

implementations these functions may be implemented as macros.<br />

s 1: 1 oop-tsqu<strong>al</strong> token keyword<br />

This is the loop token comparison function. token is any Lisp object; keyword is the<br />

keyword it is to be compared against.· It r<strong>et</strong>urns t if they represent the same token.<br />

comparing in a manner appropriate for the implementation.<br />

51: loop-tmember lokell keyword-lisl<br />

The member variant of si:loop-tequ<strong>al</strong>.<br />

s1 : 1 oop-tas soc /OkCI1 keyword-<strong>al</strong>isl<br />

The assoc \'ariant of si:loop-tequ<strong>al</strong>.<br />

The followiilg macro turns into the "proper" cude for generating a temporary variable in a<br />

particular I.ISP implementation.<br />

51: loop-gentemp &option<strong>al</strong> prcfi~r<br />

This expands into a c<strong>al</strong>l to the proper function for constructing a temporary variable.<br />

Depending on how it expands. the form prefix may not g<strong>et</strong> used (so it should not have<br />

interesting side effects!). In Nil. (and eventu<strong>al</strong>ly in some other implementations). this<br />

utilizes the gentemp function so that the generated variable wi1l be interned and<br />

somewhat mnemonic: in this case. . nrefix ... (which should he Ii ~vmhnl .,.""", nr Ii "rrino\ will .... hp<br />

used as a prefix of the generated symbol. In other implementations. si:loop-gentemp<br />

will expand to just a c<strong>al</strong>l to gensym. and throwaway prefix.<br />

If gentemp docs g<strong>et</strong> used but prefix is not supplied, then the prefix loopvar- is used so<br />

that the variable is identifiable as originating with loop.<br />

If an iteration path function desires to make an intern<strong>al</strong> variable accessible to the user, it<br />

should c<strong>al</strong>l the following function instead of si:loop-gentemp:<br />

s1 :loop-named-var1ab18 keyword<br />

This should only be caned from within an iteration path function.· If keyword has been<br />

specified in a using phrase for this path, the corresponding variable is r<strong>et</strong>urned;<br />

otherwise. si:loop-gentemp is caned and that new symbol r<strong>et</strong>urned. Within a given path<br />

function. this routine should only be caned once for any given keyword.<br />

If the user specifics a using preposition containing any keywords for which the path<br />

function does not caU si:loop-named-variabte. loop will infonn the user of his error.<br />

MC:NII.Mt\N:LOOIYrM 319<br />

23·DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 167 Iter<strong>al</strong>ion P"llls<br />

17.7.2.1 An Example Path Definition<br />

Here is an example function which defines the string -characters iteration path. This path<br />

steps a variable through <strong>al</strong>l of the characters of a string. It accepts the fonnat<br />

(loop for var bei ng the stri ng-characters of sir ... )<br />

The function is defined to handle the path by<br />

{define-loop-path string-characters string-chars-path<br />

(of»<br />

~1C:Nll.MAN;I.OOPTM 319<br />

23-DEC-83


Iteration Paths 168<br />

Nil. Manu<strong>al</strong><br />

Here is the function:<br />

(defun string-chars-path (path-name variable data~type<br />

prep~phrases inclusive?<br />

<strong>al</strong>lowed-prepositions data<br />

&aux (bindings nil)<br />

(prologue nil)<br />

string-var<br />

index-var<br />

size-var)<br />

(declare (ignore <strong>al</strong>lowed-prepositions data»<br />

(s<strong>et</strong>q string-var (si:loop-gentemp 'loop-string-)<br />

index-var (si:loop-gentemp 'loop-index-)<br />

size-var (si:1oop~gentemp 'loop-size-»<br />

To iterate over the characters of a string. we need<br />

to save the string. sav~ the size of the string.<br />

step an index variable through that range, s<strong>et</strong>ting<br />

the user's variable to the character at that index.<br />

Default the data-type of the user's variable:<br />

(cond «null data~type) (s<strong>et</strong>q data~type string-char»)<br />

; We support exactly one "prepOSition", which is<br />

; required, so this check suffices:<br />

(cond «null prep-phrases)<br />

(ferror nil "OF missing in -S iteration pat~ of -5"<br />

pa t h-name va r i ab 1 e) ) ) .<br />

; We do not support "inclusive" iteration:<br />

(cond «not (null inclusive?»<br />

(ferror nil<br />

"Inclusive stepping not supported in -S path -<br />

of -S (prep phrases c -:S)"<br />

path-name variable prep-phrases»)<br />

; S<strong>et</strong> up the bindings<br />

(s<strong>et</strong>q bindings {list (list variable nil data-type)<br />

{list string-v<strong>al</strong>' (cadar prep-phrases»<br />

(list index-v<strong>al</strong>' 0 'fixnum)<br />

(list size-var 0 'fixnum»)<br />

; Now s<strong>et</strong> the size variable<br />

(s<strong>et</strong>q prologue (list '(s<strong>et</strong>q ,size-v<strong>al</strong>' (string-length<br />

,string-var»»<br />

; and r<strong>et</strong>urn the appropriate stuff, explained below.<br />

(list bindings<br />

prologue<br />

t(= ,index-v<strong>al</strong>' .size-ver)<br />

nil<br />

nil<br />

(list variable '(char ,string-v<strong>al</strong>' ,index-v<strong>al</strong>')<br />

index-var '(1+ ,index-var»»<br />

~tC:<strong>NIL</strong>MAN:LOOPTM 319<br />

23-DEC-83


Nil. Manu<strong>al</strong> 169 Iteration Paths<br />

The first clement of the r<strong>et</strong>urned list is the bindings. The second is a list of forms to be<br />

placed in the prologu('. The remaining clements specify how the iteration is to be perfonned.<br />

This example is a particularly simple case, for .two reasons: the actu<strong>al</strong> "variable of iteration".<br />

index-var. is purely intern<strong>al</strong> (being gensymmed). and the stepping of it (1 +) is such that it<br />

may be perfonned safely without <strong>al</strong>l endtest. Thus index -var may be stepped immediately· after<br />

the s<strong>et</strong>ting of the user's variable. causing the iteration specification for the first iteration to be<br />

identic<strong>al</strong> to the iteration specification for <strong>al</strong>l remaining iterations. This is advantageous from the<br />

standpoint of the optimizations loop is able to perfonn. <strong>al</strong>though it is frequently not possible due<br />

to the semantics of the iteration (e.g.. for l'ar first ('xpr! then ('xl'r2) or to subtl<strong>et</strong>ies of the<br />

stepping. It is safe filr this path to step the user's variable in the ps('udo-sl('ps (the fourth item of<br />

an iteration specification) rather than the "re<strong>al</strong>" steps (the second). because the step v<strong>al</strong>lie C(lll<br />

have no dependencies on any other (user) iteration vari41bles. Using the pseudo-steps gener<strong>al</strong>ly<br />

results in some cflicicncy gains.<br />

I f one desired the index variable in the above definition to be user-accessible through the<br />

using phrase feature with the index keyword. the function would need to be changed in two<br />

ways. First. index-var should be s<strong>et</strong> to (si:loop-named-variable 'index) instead of the c<strong>al</strong>l to<br />

si:loop-gentemp. Secondly. the efficiency hack of stepping the index variable ahead of tie<br />

iter~tion variable must not be done. This is effected by changing the last fOim to be<br />

(list bindings prologue<br />

nil<br />

(list index-var '(1+ ,index-var»<br />

'(= ,index-var ,size-var)<br />

(list variable ~(char ,string-~ar .1naeX-Var),<br />

nil<br />

nil<br />

'(= ,index-var ,size-var)<br />

(list variable '(char ,string-var ,index-var»)<br />

Note that <strong>al</strong>though the second '( = ,index-var ,size-var) could have been placed earlier (where<br />

the second nil is). it is best for it to match up with the equiv<strong>al</strong>ent test in the first iteration<br />

specification grouping.<br />

MC:<strong>NIL</strong>MAN:LOOPTM 319<br />

23-DEC-83


The Flavor Facility 170 <strong>NIL</strong> Manuill<br />

18. The Flavor Facility<br />

IS. 1 Introduction<br />

Languages such as Sm<strong>al</strong>lt<strong>al</strong>k and Act-1 are designed to encourage a style of programming<br />

c<strong>al</strong>led object-oriented programming. LISP MACIIIJl.:E LISP offers a facility for object-oriented<br />

programming as well: it is caHed the Flavor System. or just flavors. NIl. offers a more primitive<br />

version of flavors than is available on the l.isp Machine. but unless you do quite complicated<br />

things with flavors. you will probably never notice the difference.<br />

18.1.1 Object -oriented Programming<br />

Suppose you were writing a file system. You might have sever<strong>al</strong> different types of files.<br />

including. for example. binary files and text files. If you wrote a program to print files on a<br />

user"s tenninaJ. and you wanted it to print ASCII characters when the user printed a text file. but<br />

ncwl numbers when the user printed a binary file. you might implement it as fonows:<br />

(typecase file<br />

(binary (oct<strong>al</strong>1y-print file»<br />

(text (ascii-print file»)<br />

That is. you might dispatch off the type of the file, c<strong>al</strong>ling the appropriate function to print the<br />

file. It might be nicer. however. to keep the infonnation about how the file should be printed<br />

with Ihe fill' itself. 'J11at is. the m<strong>et</strong>hod used for printing itsclfcould be part of the int(>rmation<br />

contained in each file: we could simply decide that every type of file we will support in our<br />

operating system will know how to perform certain operations. and we could specify printing on a<br />

tennin<strong>al</strong> to be one of them. Then we would implement the above as<br />

(send file :print-contents)<br />

where :print-contents is ·the name of a m<strong>et</strong>hod that could be specified for each type of file.<br />

On simply looking at the differences b<strong>et</strong>ween the two samples of code, one might notice that<br />

the second expresses much more clearly and compactly what we are doing: printing the file. We<br />

trust whoever defined this type of file object to have defined a reasonahle :print-contents m<strong>et</strong>hod<br />

for it. and we don't worry any further about type-dispatching and the like. Thus object-oriented<br />

programming constructs can have the effect of fre~ing the programmer from an extra level of<br />

d<strong>et</strong>ail.<br />

This should sound familiar even to users who have not used flavors. because it is similar to<br />

generic arithm<strong>et</strong>ic in COMMO~ LISP. In fact. operations that work for more than one type of<br />

object (like the imaginary :print-contents above) are c<strong>al</strong>led generic operations.<br />

Another thing we might notice about the object-oriented way of doing things is described by<br />

its name. We might say somewhat fancifully that the files in our example above have been raised<br />

from the re<strong>al</strong>m of "inanimate data· J<br />

to being objects that can do things. A file has become an<br />

object th<strong>al</strong> knows how to print itself. and can be asked to do so.<br />

MC:<strong>NIL</strong>MAN:FLAVOR44<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 171 Introduction<br />

Ohjects can know of things besides their m<strong>et</strong>hods for perfonning operations, and this brings<br />

up another advantage of object-oriented programming, which is useful even when one is not<br />

planning on implementing operations that will work on a large class of objects. Two objects of<br />

the same type will share the same m<strong>et</strong>hods for perfonning an operation. But two objects· of the<br />

same type can still have distinct state. They can have instance variables: variables that are loc<strong>al</strong><br />

to each instantiation. in much the same way that scoped variables arc loc<strong>al</strong> to a function c<strong>al</strong>l.<br />

For example. the file objects we were discussing above could have variables :author and :writedate.<br />

and each object would have its own v<strong>al</strong>ue for these variables.<br />

18.1.2 Object-oriented Programming llsing Flavors<br />

When we lise flanlrs to write object-oriented code. the objects themsehes are not flavors.<br />

They are ills/mr/ia/iolls of flavors. The flavor of an object is actu<strong>al</strong>ly its type. We define a flavor<br />

using ~efflavor. The definition of a flavor looks like<br />

(defflavor flavor-name inst<strong>al</strong>lce-variables<br />

com l'ol1cl1/~flavors<br />

optionl option2... )<br />

The flavor-namc can be any symhol. the ills/ancc-variables a (possibly nu11) list of symbols<br />

(variables) and their initi<strong>al</strong> v<strong>al</strong>ues. the component-flavors a list of flavors. and the options will be<br />

described further helow. A more concr<strong>et</strong>e example is:<br />

(defflavor bicycle «wheel-size nil) (gear-ratios nil)<br />

(s~l~ct~d-gear nil)<br />

(distance-travelled nil»<br />

( )<br />

:g<strong>et</strong>tab1e-instance-variables<br />

:s<strong>et</strong>table-instance-variab1es)<br />

The option :g<strong>et</strong>table-instance-variables will cause a m<strong>et</strong>hod that will r<strong>et</strong>urn the v<strong>al</strong>ue of<br />

that instance variable to be defined for each of the instance variables. :s<strong>et</strong>table-instancevariables<br />

will cause a m<strong>et</strong>hod that will <strong>al</strong>low us to s<strong>et</strong> the v<strong>al</strong>ue of that instance variable to be<br />

generated for each instance variable.<br />

If we want to create an instantiation of the flavor bicycle, we use make-instance:<br />

(s<strong>et</strong>q my-bike (make-instance ·bicycle»<br />

r<strong>et</strong>urns<br />

#<br />

or som<strong>et</strong>hing like it This object can be described:<br />

MC:<strong>NIL</strong>MAN:FLAYOR44<br />

23-I)I-:C-83


Introduction 172 <strong>NIL</strong> Manu<strong>al</strong><br />

(describe my-bike)<br />

The instance at address 128788 is of flavor BICYCLE and is 4<br />

Q's long. It directly or indirectly includes flavors (BICYCLE<br />

VA<strong>NIL</strong>LA-FLAVOR), and is of the types (BICYCLE VA<strong>NIL</strong>LA-FLAVOR).<br />

The 4 instance variables are:<br />

WHEEL-SIZE <strong>NIL</strong><br />

GEAR-RATIOS <strong>NIL</strong><br />

SELECTED-GEAR <strong>NIL</strong><br />

DISTANCE-TRAVELLED <strong>NIL</strong><br />

<strong>NIL</strong><br />

We can c<strong>al</strong>ise an instiHlllatlOn of &1 flanlr to execute ,I m<strong>et</strong>hod with send. The mctllods<br />

LT~ated upon definition of a flavor with the option :s<strong>et</strong>table-instanee-variables ha\e the n~lfncs<br />

of the instance \'ariables appended (0 "s<strong>et</strong>·n<br />

, but are in tllC keyword package. Thus we could s<strong>et</strong><br />

lhe v<strong>al</strong>ue of wheel -size like tllis:<br />

(send my-bike :s<strong>et</strong>-wheel-size 27) .<br />

The m<strong>et</strong>hods created on definition of a ftil\'Or with the option :s<strong>et</strong>tabfe-instance-variables are<br />

the same ~IS the names of the variahles. but are in the keyword paCkitge. So we could g<strong>et</strong> the<br />

,'arlle of :wheel-size like this:<br />

(send my-bike :wheel~size)<br />

27<br />

send objcct message &rest args<br />

This is the basic message-passing primitive. It should be used instead of funeaU. which<br />

has been used in the past in LISP MACIUNE LISP.<br />

1 expr-send o~iecl message &rest args<br />

This is to send as lexpr-fune<strong>al</strong>l (which is apply (page 31). as it is defined now) is to<br />

funeaU.<br />

There must be at least one arg given~ and the last one must be either a list or a vector.<br />

The object is sent message with arguments of <strong>al</strong>l of the other args followed by <strong>al</strong>l the<br />

elements of the last arg.<br />

send-forward object message {arg}-<br />

This is only v<strong>al</strong>id within the lexica1 scope of a defm<strong>et</strong>hod definition.<br />

L<strong>et</strong> the flavor which this m<strong>et</strong>hod was defined on be caned jlav. send-forward then does<br />

a s~nd, but stans searching for m<strong>et</strong>hods to handle message after jIav.<br />

n.b. send-forward is neither as efficient as it should be nor as efficient as one would like.<br />

y<strong>et</strong>. Note that it can be used 10 acheive many of the same effects as m<strong>et</strong>hod combination.<br />

MC:NfI.MAN:t:I.AVOR 44<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 173<br />

Introduction<br />

1 expr-send-forward ()~iecl message {arg}*<br />

Like lexpr-send. but does send-forward.<br />

mak.e-i ns tance jla\'o~llame &rest keyworded-argumel1ts<br />

This is the primary instantiation function. The keyworded-argumellls arc <strong>al</strong>ternating<br />

keywords and v<strong>al</strong>ues. Typic<strong>al</strong>ly, they specify initi<strong>al</strong> v<strong>al</strong>ues for the instance variables which<br />

arc initable (as specified with the :initable-instance-variables option to defflavor). '1l1ey<br />

may <strong>al</strong>so be arbitrary keywords which are checked for v<strong>al</strong>idity against those specified with<br />

the :init-keywords option to defflavor. which (merged with the :init-piist specification to<br />

defflavor) will be passed as arguments to the :init m<strong>et</strong>hod of the flavor.<br />

deffl avor jlcl\'UI~l1ame<br />

illsl<strong>al</strong>lce-varhlbles illc/uded-jlm'ors oplions ..•<br />

flawr-nlll1ll' is the name of the flavor being defined. After it is defined. it is acceptable as a<br />

second argument to typep (page 18), which will r<strong>et</strong>urn t if given a second argument of flavor­<br />

Ilame and a first argument of an instantiation of jlayo""llwl1e. or any other flavor which directly or<br />

indirectly includes jla\'o~l1<strong>al</strong>l1e.<br />

iIlS/Llllce- rariablcs is a list of inswnce variables or lists of instance variables and forms to e\'<strong>al</strong><br />

to ohtain their initi<strong>al</strong> v<strong>al</strong>ues. These arc not necessarily <strong>al</strong>l of the instance variables of the<br />

instance: some may be inherited from other flavors which jlavor-name is being built from.<br />

However. compiled flavor m<strong>et</strong>hods for jlavor-name may not know about those inherited instance<br />

variables. so if you "know" that a flavor is going to have certain variables and need to use them.<br />

Y01l c;h(\t'~d inc1udr them h('r~. (Note that in the current ~:!!. !ns~ncc '."3:-bh1~ inh~r!tmcc is<br />

perfonlled when the defflavor form is compiled. so one will not receive a diagnostic about this.<br />

The inheritance will be deferred in in some later release. however. to provide for other features.<br />

including the ability to not have the component flavors of flavor-name defined when the defflavor<br />

is being compiled or interpr<strong>et</strong>ed.)<br />

If an atomic instance variable is specified in the instance variables list. then the instance<br />

variable is initi<strong>al</strong>ized "unbound" by make-instance (assuming no initiaHzation was specified with<br />

make-instance). This will cause an unbound variable reference in the 1\IL interpr<strong>et</strong>er; extern<strong>al</strong><br />

("outside accessible") references will just pick out the unbound pointer. as will compiled<br />

references to the instance variable, and probably cause some spastic behavior later.<br />

Otherwise, the instance variable specification should be a list of the ins~1nce variable and an<br />

initi<strong>al</strong>ization fonn, which will be ev<strong>al</strong>uated to d<strong>et</strong>ermine the initi<strong>al</strong> v<strong>al</strong>ue. (<strong>NIL</strong> actu<strong>al</strong>ly does not<br />

use ev<strong>al</strong>, but stores the v<strong>al</strong>ue either as a constant, if it self-ev<strong>al</strong>uates, or as a function of no<br />

arguments which ev<strong>al</strong>uates the initi<strong>al</strong>ization form; this function will be compiled when the<br />

defflavor fonn is compiled.)<br />

The following defflavor options <strong>al</strong>l de<strong>al</strong> with instance variables which must be listed in the<br />

instance-variables given for the defflavor. They may appear as atomic options, like :g<strong>et</strong>tableinstance-variables<br />

and :s<strong>et</strong>table-instance-variables in the bicycle example (page 171). in<br />

which case they refer to an of the instance-variables of the defflavor, or listed with those hey<br />

pertain to, as in<br />

MC:<strong>NIL</strong>MAN:FLAVOR 44<br />

23-I)EC-83


Introduction 174<br />

Nil. Manu<strong>al</strong><br />

(defflavor frob (var-l var-2 var-3) ()<br />

:g<strong>et</strong>table-instance-variables<br />

(:s<strong>et</strong>table-instance-variables var-l var-2»<br />

in which var-1. var-2. and var-3 are <strong>al</strong>l :g<strong>et</strong>table. but only var-l and var-2 are :s<strong>et</strong>table.<br />

:g<strong>et</strong>table- instance - variables<br />

Causes automatic generation of m<strong>et</strong>hods which will· f<strong>et</strong>ch the v<strong>al</strong>ues of the specified<br />

instance variables. ...:ach m<strong>et</strong>hod name is the name of thc variablc interned in the<br />

keyword package. Thus in the bicycle eX&lmple. one may send a bicycle the :distanc<strong>et</strong>ravelled<br />

message to find how far the bicycle h


---_.-._-----_.<br />

<strong>NIL</strong> Manu<strong>al</strong> 175 Introduction<br />

one. and make-instance is supposed to barf if that is not the case.<br />

:required - m<strong>et</strong>hods<br />

Any flavor including this flavor is required to support the listed m<strong>et</strong>hods. This is <strong>al</strong>ledgely<br />

checked ell instantiation time.<br />

:no-vanilla -flavor<br />

Do not include vanilla -flavor. as is done by default.<br />

:included- flavors<br />

Sort of like building the flavor from the named flavors. but they are made to come last<br />

<strong>al</strong>ways. where is l1ie illli('ril<strong>al</strong>lcc-orci('r <strong>al</strong>ld \'llllilla~tla\'(}r insertioll <strong>al</strong>ld tlJis ('xplain('d?<br />

:flavor - not - instantiable<br />

This flanlr is not itself inswntiahlc. This should he specified for things which are not<br />

compl<strong>et</strong>e in thcmsrlves. hut mixill jlavors-flavors which arc meant to be mixed in to<br />

provide some aspel.:l of other flavors.<br />

:init- keyw~rds<br />

AJlowa[~ie keywords which make-instance will pass <strong>al</strong>ong to the :init message when a<br />

fbvor is instantiated.<br />

:default-init-plist<br />

Alternating keyword-v<strong>al</strong>ues. which are supplied to the :init message when a flavor is<br />

instantiated. unless the keyword was supplied <strong>al</strong>ready to make-instance.<br />

:documentation<br />

ummmm<br />

defm<strong>et</strong>hod (flQ\lor-name message-name [message-type» arglist body ...<br />

Defines a m<strong>et</strong>hod m(,ssage-name for flavor. message-type is not supported. do not use it.<br />

arglist is any lambda-list acceptable to <strong>NIL</strong>. self will be bound (lexic<strong>al</strong>ly) for the<br />

ev<strong>al</strong>uation of body.<br />

Lexic<strong>al</strong> instance variables are correctly enclosed by the <strong>NIL</strong> interpr<strong>et</strong>er in this version of<br />

<strong>NIL</strong>. The only time this can fail is if there is any funny stuff with how the definition is<br />

being perfonned, like ev<strong>al</strong>uating a defm<strong>et</strong>hod inside the lexic<strong>al</strong> environment of another<br />

defm<strong>et</strong>hod or a defun. This would not work compiled anyway.<br />

defm<strong>et</strong>hod-primi t iva (flavor-name message-name) arglist body ...<br />

lbis is used to define a m<strong>et</strong>hod without interfacing to de<strong>al</strong> with the self variable or the<br />

instance variables. 111e arguments which the generated function receives wi11 be the object,<br />

the map vector, the message, and the other arguments. This routine exists primarily for<br />

primitive low-level m<strong>et</strong>hod-generation code, as that which might be used by defstruct.<br />

MC:<strong>NIL</strong>MAN:FI.AYOR 44<br />

23-I)EC-83


System-Defined Messages 176 Nn~ Manwll<br />

18.2 System" Defined Messages<br />

Here are. some of the messages the system uses to de<strong>al</strong> with objects defined by defftavor. and<br />

what they mean. .<br />

:print-self strtam level slashifrp<br />

The object should print itself to the stream sitcam. level is the recursion level of printing.<br />

and should be compared against the dynamic v<strong>al</strong>ue of prinlevel. slashify·p being non-null<br />

mC.tnS that thc output should maybe be re-readable: it is bcing done by prinl rather than<br />

prine.<br />

If you use this in a non-trivi<strong>al</strong> fashion (specific<strong>al</strong>ly. if the object will he printed in a nonatomic<br />

fllshion). then it might be re'lsomlble to define m<strong>et</strong>hods fhr the pr<strong>et</strong>ty-printcr using<br />

thc :pp-dispatch and :pp-anaphor-dispatch m<strong>et</strong>hods. ,md define the non-pr<strong>et</strong>ty-printing<br />

:print-self m<strong>et</strong>hod in tenns of how the pr<strong>et</strong>ty-printing is perfonned. This is described in<br />

[7].<br />

: equa 1 uthe,...object<br />

The m<strong>et</strong>hod should r<strong>et</strong>urn t if its object is equ<strong>al</strong> to olher"()~iec(. nil if it is not. olhe,...<br />

object will be of the ex(\ct same type as the object receiving the mess~1ge (a consequence<br />

of the fonn<strong>al</strong> definition of equ<strong>al</strong>. page 20). This message is <strong>al</strong>so used by eqf (page 20)<br />

on numeric<strong>al</strong> types which arc not "primitive" <strong>NIL</strong> data types.<br />

:sxhash<br />

The object should r<strong>et</strong>urn a hash encoding of itself. such that two objects which are equ<strong>al</strong><br />

have the same hash. See the description of sxhash. page 119, for the semantics which<br />

must be enforced, and note <strong>al</strong>so the default :sxhash m<strong>et</strong>hod. page 177.<br />

:8v<strong>al</strong><br />

AJIows extending the ev<strong>al</strong>uator in strange and wondrous ways to handle ev<strong>al</strong>uation of nonlist<br />

fOnTIs. Note that certain types which arc defined· to self-ev<strong>al</strong>uate do so by spcci<strong>al</strong> case<br />

checks in the interpr<strong>et</strong>er, so one cannot change the ev<strong>al</strong>uation behaviour of those types.<br />

The compiler can't handle these extensions however.<br />

: func<strong>al</strong>1 argument-vector<br />

This is what happens by default when a func<strong>al</strong>. is performed on an instance. argumentvector<br />

is a stack vector (section 3.1, page 15) of the arguments.<br />

: describe ?arguments?<br />

This is what is used by the describe function (page 222).<br />

:exh1b1t-self stream<br />

:select-nth n<br />

: store-nth n v<strong>al</strong>ue<br />

These are used by the exhibit function (page 222) to define how exhibition is perfonned<br />

on objects of the given type. lbsic<strong>al</strong>ly. exhibition is initiated by sending the objccta<br />

:exhibit-self message; it should respond by printing out the appropriatc infonnation. and<br />

r<strong>et</strong>urning the nUlnbcr of "slots" Of "indiccs" which it includes. (Try exhibiting various<br />

l'IL objects to see the fonnat: do not include ule clear-screen in the display. The indices<br />

MC:NII.MAN;FLA VOR 44<br />

23-DEC-83


iiutitT<br />

W<br />

Nil. Manu<strong>al</strong> 177 Message I )efaults<br />

printed out in the initi<strong>al</strong> display are printed by this m<strong>et</strong>hod.} Then. the ohject will be<br />

sent (as the llserinteracts) :select-nth and :store-nth messages to select' and store the<br />

corresponding components. GeneraHy.there is no need to define such a m<strong>et</strong>hod for<br />

ordinary flavors. as the m<strong>et</strong>hod inherited from vanilla-flavor will show the instance<br />

variable names <strong>et</strong>c.<br />

: pp-d1 spatch lonnat-description?<br />

:pp-anaphor-d1spatch<br />

These are used hy the !,:1I. pr<strong>et</strong>ty-printer [7]. :pp-dispatch is used to control formatting:<br />

to use this you will need to eonsult the pr<strong>et</strong>ty-primer documentation. :pp-anaphordispatch<br />

is used lO d<strong>et</strong>ect circularities in the structure heing printed: <strong>al</strong>l that is nOlm<strong>al</strong>ly<br />

needed is to c<strong>al</strong>l the fUI1l:tion pp-anaphor-dispatch on each of the components which<br />

will he printed by the :pp-dispatch m<strong>et</strong>hod. These m<strong>et</strong>hods should be defined in pairs.<br />

so that they refer to the same s<strong>et</strong> of components.<br />

18.3 Message Defaults<br />

Here are some of the messages provided by vanilla-flavor. and what they do.<br />

: p r i n t - se 1 f stream level 'slashify-p<br />

Prints som<strong>et</strong>hing vaguely infonnative.<br />

: g<strong>et</strong>-handl er-for messa~e-name<br />

R<strong>et</strong>urns the handler function for the message message-name. or nil. In NIl.. this is.<br />

necessarily of type compiled-function.<br />

: operat 1 on-handled-p message-flame<br />

R<strong>et</strong>urns a non-nun v<strong>al</strong>ue if the object supports a message message-name, nil otherwise.<br />

:send-if-handles message &rest args<br />

If the objcct supports message t then it is sent that message with arguments of whatever<br />

args were passed; otherwise, nil is r<strong>et</strong>urned.<br />

:wh1ch-operations<br />

A list of aU of the messages which the object handles is r<strong>et</strong>urned.<br />

dynamic<strong>al</strong>ly and cached on a per-flavor basis.<br />

This is computed<br />

:equ<strong>al</strong><br />

By default, two objects are equ<strong>al</strong> only if they are eq. If the object has interesting<br />

criteri<strong>al</strong> components, it must define an equ<strong>al</strong> message to compare them.<br />

:sxhash<br />

The default :sxhash simply r<strong>et</strong>urns a hash computation on the name of the flavor. The<br />

reason for thi!\ is that if two objects are equ<strong>al</strong>. their sxhashes must be equ<strong>al</strong>. So, if the<br />

object docs anything interesting for the :equ<strong>al</strong> message. it should probably define a<br />

compatible :sxhash message so that different objects will hash differently,<br />

MC:NII.MAN:FLA VOR 44<br />

23-DEC-83<br />

- . ,<br />

- ~~ ~ -' - ... - - - - '<br />

, '<br />

~ "4' ~ •<br />

~: ~. ' , ,-' ..:, ," ; _..', " .<br />

- ", -. ,- . . '


Message J}efaults<br />

:8xh1b1t-self stream<br />

:s818ct-nth 11<br />

: store-nth 11 v<strong>al</strong>ue<br />

178<br />

Nfl. Manu<strong>al</strong><br />

'Ibe default exhibition m<strong>et</strong>hod displays the <strong>al</strong>l of the instance vari,lbles of the instance.<br />

and their v<strong>al</strong>ues. The selcct and store m<strong>et</strong>hods just <strong>al</strong>low onc to felCh and modify the<br />

variables by index.<br />

: pp-d1 spatch jOnllat-dcscripliol1?<br />

The defillilt :Pp-dispatch m<strong>et</strong>hod "reily-prints the object the way it "rint~ (vi,1 :printself).<br />

,lIld treat~ il as iIIomic. If you define a :print-self m<strong>et</strong>hod for som<strong>et</strong>hing. the :pp_<br />

dispatch m<strong>et</strong>hod ma} n(n fimction 'I~ desired. in Ill<strong>al</strong> it will nnl dn any "mn<strong>al</strong>lil1g nf the<br />

components.<br />

:pp-anaphor-d1spatch<br />

The default :pp-anaphor-dispatch m<strong>et</strong>hod dnes nothing. nn the grounds that the :pp_<br />

dispatch m<strong>et</strong>hod will not be· printing any comp{)ncnt~.<br />

MC:<strong>NIL</strong>MAN:FLAVOR 44


<strong>NIL</strong> Manu<strong>al</strong> 179 Input, Output. and Streams<br />

19. Input, Output, and Streams<br />

Input and output in <strong>NIL</strong> is pcrfonncd by operations on streams. Some streams can operate in<br />

only onc direction (input or output), and some can operate in both.<br />

str8amp x<br />

R<strong>et</strong>urns t if x is a stream. nil otherwise.<br />

Most operations on streams are perfonned by functions which take the stream as one of its<br />

arguments. possihly defaulted. Although ultimatc1y the stream operations turn into messagepassing<br />

using the flavor system. these thnctions arc the pertcrrcd way to do things. as they<br />

pert(lnll what mediation might be necessary b<strong>et</strong>ween the desired eflect and the stream's<br />

~apabi1ities.<br />

19.1 Standard Streams<br />

The folJowing variables have as their \'ah1es streams used for variolls purposes. In the future,<br />

the names will b\.' changed to have • characters at both ends; e.g.. standard - input wi11 become<br />

·standard- input •.<br />

standard-1 nput<br />

Variable<br />

This is used as the default stream for various input functions. and for the toplevel and<br />

breaklevel loops.<br />

standard-output<br />

Variable<br />

This is used as the default stream for various output functions. and for the top level and<br />

breaklevel loops.<br />

termin<strong>al</strong>-io<br />

Variable<br />

The v<strong>al</strong>ue of termin<strong>al</strong>-io is ordinarily the stream which connects to the user's console.<br />

error-output<br />

Variable<br />

This is the stream to which error messages should be sent Nonn<strong>al</strong>ly, it directs output<br />

through the v<strong>al</strong>ue of termin<strong>al</strong>-io (but see comments below), but it could be made to<br />

send them to a file. for instance. (This may not be used properly y<strong>et</strong>.)<br />

query-10<br />

Vanabk<br />

This stream is used to ask questions of the user. Norm<strong>al</strong>1y it uses the tennin<strong>al</strong>, but could<br />

be made to (for instance) log both the input and the output of the transactions .<br />

• trace-output.<br />

Variable<br />

This is the stream to which output from tracing (see the trace function. page 220) is sent<br />

All of the above streams. with the exception of termin<strong>al</strong> -io. are initi<strong>al</strong>ly bound to synonym<br />

streams which pass <strong>al</strong>l operations on to the stream which is the v<strong>al</strong>ue of termin<strong>al</strong>-io.<br />

MC:<strong>NIL</strong>MAN;NEWIO 27<br />

23-DEC-83<br />

.. ' '. . ... ". .... :;'::/:. .<br />

. '. .' . ..'<br />

.<br />

. '.. . ..<br />

_ ~ " • - , c'. :_::- . " ' _. ' _ ' . _ _ ,- "'. "


Stream Creation and Operations 180 Nil. ManuaJ<br />

The v<strong>al</strong>ue of termin<strong>al</strong>-io should not nonn


Slream Creation and Operations ]82 NI14 Manu<strong>al</strong><br />

make-synonym-stream symbol<br />

This milkes a S)'1I01lYIl1 stream. Such ,t stremn directs (most) operations on it to the<br />

current dynamic binding of the variable symbol. In this way. the stream produced can<br />

<strong>al</strong>ways be indirecting to another stream, even when the v<strong>al</strong>ue of symbol changes by its<br />

being bound Of s<strong>et</strong>qed.<br />

make-str1ng-output-stream &option<strong>al</strong> &key (:Iine-Iength 79) (:line-number 1)<br />

(:page-fength 60) (:page-number 1) (:character-position 0)<br />

This crc.Hes a stream which wi11 "ccumulate <strong>al</strong>l .output given tn it. This output may be<br />

obtained as a string by g<strong>et</strong>-output-stream-string, be1ow.<br />

The optiolls are used to initi.tlil.e various param<strong>et</strong>ers of the stre4lrn. so th<strong>al</strong> f


<strong>NIL</strong> Manu<strong>al</strong> 183 Input Functions<br />

19.3 Input Functions<br />

First some functions not specific to ascII mput streams (necessarily). listen and clear-input<br />

could conceivably be meaningful on strange peripher<strong>al</strong>. devices (dreamer, aren't i?).<br />

listen &option<strong>al</strong> input-stream<br />

lllis will r<strong>et</strong>urn nil jf there is no input immediately available from input-sream. non~null<br />

otherwise. On a termin<strong>al</strong>. the intent is that it tells wh<strong>et</strong>her the user has typed some input<br />

which has not been read y<strong>et</strong>. On non-interactive streams it should be true except at endof-file:<br />

most streams probably don't SUppOft it y<strong>et</strong>.<br />

clear-input &oplion<strong>al</strong> input-strcam<br />

Flushes bufiered input from input-stream. This only works on the termin<strong>al</strong> right now. (It<br />

isn '( re<strong>al</strong>ly meaningful for non-interactive streams.)<br />

19.3.1 Ascii Input<br />

Most of the functions which read input t(ike arguments input-strcam and eofmlue. In gener<strong>al</strong>.<br />

if input-stream is nil Of not supplied. it defaults to the v<strong>al</strong>ue of standard-input: if it is the atom<br />

1. the v<strong>al</strong>ue of termin<strong>al</strong>-io will be used.<br />

If no eofv<strong>al</strong>ue is specified. then an error will be sign<strong>al</strong>led at end-of-file. otherwise the eof<br />

v<strong>al</strong>ue will be r<strong>et</strong>urned. Specifying an eofv<strong>al</strong>ue of nil is 110/ equiv<strong>al</strong>ent to specifying no eofv<strong>al</strong>ue,<br />

When input is read from an interactive stream, the characters typed will be echoed at the<br />

user. For those functions which do some significant amount of reading. such as readline or read.<br />

rubout processing will be provided. In this case. specifying an eofv<strong>al</strong>ue means that if the user<br />

auempts to ttruh oul" past the beginning of what he was typing, the function will r<strong>et</strong>urn ('of<br />

v<strong>al</strong>ue. instead of requiring him to type a compl<strong>et</strong>e expression (line, s-expression, whatever the<br />

function c<strong>al</strong>ls for).<br />

What actu<strong>al</strong>ly happens right now is that specifying an eofv<strong>al</strong>ue when reading from an<br />

interactive stream, dies.<br />

read-char &optionaJ input-stream eofv<strong>al</strong>ue<br />

Reads one character from input-stream.<br />

This doesn't seem to take eofv<strong>al</strong>ue y<strong>et</strong>?<br />

peek-char &option<strong>al</strong> input-stream eofv<strong>al</strong>ue<br />

Ibis definition is wrong. The arguments should be peek-type. illput-slream, eofv<strong>al</strong>ue. It<br />

will eventu<strong>al</strong>ly be fixed.<br />

Peck- at a character in the input stream. Like read-char. but the next c<strong>al</strong>l to read-char<br />

will r<strong>et</strong>urn the same character.<br />

MC:<strong>NIL</strong>MAN:NEWIO 27<br />

23-DEC-83


---------------------------------------~====::::.::==--......<br />

5.7.7 •<br />

.,r.~.r.?..-r.. 1I1I1I1I<br />

Output Functions 184 <strong>NIL</strong> Manu<strong>al</strong><br />

unread-char character &option<strong>al</strong> input-stream<br />

Undoes a read -char. peek -char. in the simple case, could have been (som<strong>et</strong>imes. is)<br />

defined as being a read-char followed by an unread-char of the character just read.<br />

Input streams are only required to support the ability to baclC up one character:<br />

unread -chars without intervening read -chars are an error.<br />

multiple<br />

re8dl1 n8 &option<strong>al</strong> input-stream eofv<strong>al</strong>ue<br />

Reads a 1ine of text from input-stream and r<strong>et</strong>urns it. as a string.<br />

r<strong>et</strong>urned. which is t if end-of-file was reached. nil otherwise.<br />

A second v<strong>al</strong>ue is<br />

read &option<strong>al</strong> iI/put-stream ('ofv<strong>al</strong>u('<br />

Reads one s-expression from inpul-slream. and r<strong>et</strong>urns it.<br />

discllssed in section 16.3. page 126.<br />

Reading and reader syntax is<br />

19.3.2 Ilinary Input<br />

The semantics of binary input arc stream specific. In gener<strong>al</strong>. integers of some significance<br />

are read. and Nil. places no speci<strong>al</strong> interpr<strong>et</strong>ation on any particular v<strong>al</strong>ues. The only sort of<br />

binary input <strong>NIL</strong> supports. however. only reads unsigned eight-bit bytes from disk files.<br />

read-byte input-stream &option<strong>al</strong> eofv<strong>al</strong>ue<br />

Reads one byte from input-strt'(lm and r<strong>et</strong>urns it as an integer. unless end of file is<br />

reached. in which case the nonn<strong>al</strong> end-of-file behaviour occurs.<br />

19.4 Output Functions<br />

Similar to the input functions. if an option<strong>al</strong> output-stream argument is not supplied to an<br />

output function. it defaults to the v<strong>al</strong>ue of standard-output.<br />

First some functions applicable to both ascii and binary streams.<br />

force-output oU/put-stream<br />

The purpose of force-output is to ensure that no output which may have been produced<br />

is sitting around in anyone's buffers. If output-stream is buffered by <strong>NIL</strong>. the output<br />

should be sent to the operating system (or whatever). and if necessary, the operating<br />

system told to send the contents of its buffers off to their eventu<strong>al</strong> destination.<br />

In practice this doesn't do anything y<strong>et</strong> in <strong>NIL</strong>.<br />

f1 n 1 sh-output output-stream<br />

This is like force-output. and addition<strong>al</strong>ly docs not r<strong>et</strong>urn until the output has actu<strong>al</strong>ly<br />

reached its destination.<br />

If a stream docs not handle this. which no currently implemented <strong>NIL</strong> streams do, a<br />

force-output is done. q.v.<br />

MC:NII.MAN:NEWIO 27<br />

23-DEC-83


<strong>NIL</strong> ManU4l1 185 Output Functions<br />

c188r-output oU/pllI-stream<br />

The Pllll10se of this is to cause as lillIe as possible of any output <strong>al</strong>ready sent to ou/pu/­<br />

s/re<strong>al</strong>l1 to reach its destination: just as force-output attempts to g<strong>et</strong> <strong>al</strong>1 buffers sent off,<br />

clear-output attempts to g<strong>et</strong> <strong>al</strong>l buffers flushed.<br />

"Ibis is primarily intended for tennin<strong>al</strong>s. <strong>al</strong>though it could be meaningful for random<br />

other devices (ascii and binary). It does not do anything. and is not re<strong>al</strong>ly expected to.<br />

to a random disk file.<br />

It doesn't do anything to anything in <strong>NIL</strong><br />

19.4.1 Ascii Output<br />

write-char char &option<strong>al</strong> output-stream<br />

Writes char to (}utpu/-slream.<br />

terpr 1 &option<strong>al</strong> OUlpul-s/ream<br />

fresh-line &optionaJ Oli/pul-stream<br />

terpri perfonns a newline on oUlpu/ .. stream.<br />

fresh -line does so. unless it can d<strong>et</strong>ennine that the "cursor" is at the left margin.<br />

fresh-line is supposed to r<strong>et</strong>urn t if it perfonned a newline. nil otherwise. terpri <strong>al</strong>ways<br />

r<strong>et</strong>urns nil. fllr historic<strong>al</strong> reasons.<br />

ous tr strillg &option<strong>al</strong> oUlpul-stream (start 0) COUllt<br />

Standard !':Il. string-output. Outputs the characters of string, starting at index slart and<br />

proceeding for count characters, to oUlpu/-stream. This is not defined by CO!\1MOi' lISt>.<br />

but has been in <strong>NIL</strong> for some time and is extremely useful for doing efficient output<br />

because it passes a pseudo-substring defined by start and· count <strong>al</strong>ong· to the stream. Most<br />

<strong>NIL</strong> streams do this more efficiently than single-character output, especi<strong>al</strong>ly the· termin<strong>al</strong><br />

stream.<br />

wr 1 t8-str 1 ng sIring &option<strong>al</strong> stream<br />

wr 1 te -11 n e string &option<strong>al</strong> stream<br />

Writes the characters of string to stream. write-line fol1ows them by a newline (terpri,<br />

page 185). In <strong>NIL</strong> this is <strong>al</strong>most <strong>al</strong>ways faster than using a loop of write-chars.<br />

pr1 nc object &option<strong>al</strong> output-stream<br />

pri n1 object &option<strong>al</strong> output-stream<br />

pr 1 nt object &option<strong>al</strong> output-stream<br />

Standard Maclisp-style printing functions.<br />

prin1 is the basic printing function, which attempts to output the printed representation of<br />

object to output-stream in such a way that it might be reconstructable with read. No<br />

. newline or \\hitespace of any kind is output before or after, so delimiters of some sort<br />

might be needed b<strong>et</strong>ween successive c<strong>al</strong>ls.<br />

MC:<strong>NIL</strong>MAN:NEWIO 27<br />

23-DEC-83<br />

. . .,.. ..... ",- -<br />

..... ~. -./"- : ~~ - ~.. -<br />

. .•. . ... ... . ..~... .•.... ~:. ;~~' ~ r:~:';; ~;:; ~~i;.··~ ,..~ ~~,~ ~,~~:~~ '-..;:;.:!C:,C;:?1::.,'.: .' / . .:. .


• 0>' , • .';,', ,-~.,<br />

• :,' ~<br />

~'<br />

:. :~.~-~::; .". ',':, '-:~ '.


<strong>NIL</strong> Manu<strong>al</strong> 187 Fonnat<br />

In r\1I .• pr<strong>et</strong>ty-prinl attempts to d<strong>et</strong>ennine the existence of circular structure. and show<br />

this somehow without blowing up.<br />

The pr<strong>et</strong>ty-printer itself is described in much more d<strong>et</strong>ail in [7].<br />

pr<strong>et</strong>ty .. pr1 nt ()~iccl &option<strong>al</strong> stream<br />

pr<strong>et</strong>ty-prinl. with a terpri first and output of a space character after. This. pr<strong>et</strong>ty-print<br />

is to pr<strong>et</strong>ty - prin 1 as print is to prin 1.<br />

oNccl &oplion<strong>al</strong> stream<br />

Like pr<strong>et</strong>ty-prinl. but does 1101 assume that ol~irci<br />

pr<strong>et</strong>ty~pr1nl-datum<br />

is l.ISP code.<br />

pr<strong>et</strong>ty-pr1nt-datum ()l~irct<br />

Similar.<br />

&option<strong>al</strong> stream<br />

19.6 Format<br />

This section is a quick reworking of the chapter on format which appeared m [3]. It omits<br />

topics specific to implementations of format other than Nil's. and includes references to<br />

differences b<strong>et</strong>ween what <strong>NIL</strong> currently provides. and the definition of format provided by<br />

CO\.1MO!': LISP. It is not known at this time how the COM\40N LISP definition of format wi11 affect<br />

the MACUSP implementation. which utilizes the same source code as the ~J1. implementation right<br />

now. The ~IL version of format will of course be made to confonn to the CO~1MO:--'; LISP<br />

definition.<br />

format destillation cOlztro/·string &rest args<br />

format is used to produce fonnatted output. format outputs the characters of collIro/­<br />

SIring. except that tilde C'-tt) introduces a directive. The character after the tilde.<br />

possibly preceded by arguments and modifiers, specifics what kind of fonnatting is desired.<br />

Some directives use an element of args to create their output.<br />

The output is sent to destination. If destillation is nil. a string is created which contains the<br />

output. If destination is t, the output is sent to the "default output destination", the v<strong>al</strong>ue of<br />

standard-output (page 179). Otherwise, destination should be an output stream.<br />

?fot'mat destination comro/-string &rest args<br />

This is equiv<strong>al</strong>ent to format except that destillation is interpr<strong>et</strong>ed just like the stream<br />

argument to print-nil means "the default" (the v<strong>al</strong>ue of standard-output), and t means<br />

"the tennin<strong>al</strong>" (the v<strong>al</strong>ue of terminaf-io). This only ,exists in MACLISP and <strong>NIL</strong>.<br />

A directive consists of a tilde. option<strong>al</strong> decim<strong>al</strong> numeric param<strong>et</strong>ers separated by commas.<br />

option<strong>al</strong> colon (n;") and atsign ("@") modifiers. and a single character indicating what kind of<br />

directive this is. The <strong>al</strong>phab<strong>et</strong>ic case of the character is ignored. Examplcs of control strings:<br />

"-S"<br />

This is an S directive with no param<strong>et</strong>ers.<br />

"-3 t 4 :@s" 'This is an S directive with two param<strong>et</strong>ers, 3 and 4,<br />

and both the colon and atsign flags.<br />

MC:<strong>NIL</strong>MAN;NEWIO 27<br />

23-I)EC-83


Format 188 <strong>NIL</strong> Manu~11<br />

format includes some extremely complicated and speci<strong>al</strong>ized features. It is not necessary to<br />

understand <strong>al</strong>l or even most of its features to use format cfficiently. The beginner should skip<br />

ovcr anything in thc fo1Jowing documentation that is not immediately useful or clear. The more<br />

sophisticated features are there tilr the convenience of programs with complicatcd fonnatling<br />

requirements.<br />

Som<strong>et</strong>imes a numcric paramcter is used to specify a character, for instance the padding<br />

character in a right- or left-justifying operation. In this case a single quote (') fol1owed by the<br />

dcsircd ch.tractcr may be used as a numeric argument. Fur example. you can use<br />

"-5. 'Od"<br />

to print a decim<strong>al</strong> numhcr in five columns with Icading zcros (the first two param<strong>et</strong>ers to -0 ar<strong>et</strong>hc<br />

number of columns and the padding character).<br />

In place of a numeric param<strong>et</strong>er to a dircctive. you C,1Il put the l<strong>et</strong>ter v. which takes an<br />

ilrgumcnt from args as a param<strong>et</strong>er to the directive. Nonn<strong>al</strong>ly this should be a number but it<br />

doesn't rea1Jy ha\'c to be. '111is feature <strong>al</strong>10ws variable column-widths and the like. Also. you can<br />

use thc character # in place of a param<strong>et</strong>er: it represents the number of arguments remaining to<br />

be processed.<br />

It is possible to have a directive name of more than one character. The name need simply be<br />

enclosed in backslashes (U' tt); for example,<br />

(format t tt-\\now\\" (status daytime»<br />

lbe backslashes above are doubled. because hackslash is the quoting character in COMMON LISP.<br />

Bec:!t!sc of this. t.'1~ fer!.':!rd-sbsh Chaf:lctcr {I} '.'.'iH prob:lbly be mnde synonymou:; with buckslush.<br />

but as of y<strong>et</strong> it has not been. As <strong>al</strong>ways. case is ignored here. There is no way to quote a<br />

backslash in such a construct No multi-character operators come with format.<br />

Once upon a time. various strange and wonderful interpr<strong>et</strong>ations were made on c01l1ro/-slring<br />

when it was neither a string nor a symbol. Some of these are still supported for compatibility<br />

with existing code (if any) which uses them; new code. however, should only use a string or<br />

symbol for cOlltro/-string.<br />

19.6.1 The Operators<br />

Here are the operators.<br />

-A arg, any USP object, is printed without slashification (like prine). - nA inserts spaces<br />

on the right. if necessary,' to make the column width at least n.<br />

-millcol.colillc.millpadpadeharA is the rull fonn of -A. which <strong>al</strong>lows <strong>al</strong>eborate control<br />

of the padding. lbe string is padded on the right with at least millpad copies of<br />

padchar: padding characters are then insened colinc characters at a time until the tot<strong>al</strong><br />

width is at least mincol. The defaults are 0 for minco/ and minpad. 1 for colinc, and<br />

space for padehar. The atsign modifier causes the output to be right-justified in the<br />

field instead of left-justified. (The same <strong>al</strong>gorithm for c<strong>al</strong>culating how many pad<br />

characters to output is used.) The colon modifier causes an arg of nit to be output as<br />

O.<br />

-S This is identica1 to -A except that it uses prinl instead of prine.<br />

MC:Nll_MAN:fORMAT 7<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 189 Format<br />

-0 Decim<strong>al</strong> output. arg is printed as a decim<strong>al</strong> integer. -11,111.00 lIses a column width<br />

of II. padding on the left with pad-character III (default of space). using the character<br />

(} (default comma) to separate groups of three digits. These commas are only inserted<br />

if the : modifier is present. Addition<strong>al</strong>ly. if the @ modifier is present. then the sign<br />

character will he output uncondition<strong>al</strong>ly: noml<strong>al</strong>ly it is only output if the integer is<br />

negative. If arg is not an integer. then it is output (using prine) right-justified in a<br />

field 11 wide. using a pad-character of m. with decim<strong>al</strong> output radix and trailing<br />

decim<strong>al</strong> point suppression.<br />

If arg is not an integer. then it is output in the specified field (as hy -A). in<br />

decim<strong>al</strong>.<br />

-0 Oct<strong>al</strong> output. Just like -0: if a"g is not an integer. it is output (as by -A). in oct<strong>al</strong>.<br />

-8 Similar. but hinary (base 2).<br />

-p If arg is not the integer 1. ,1 lower-case "s" is printed. ("P" is for "plur<strong>al</strong>".) -:P<br />

docs the same tlling. after hacking up an argument (like .. -:.... below): it prints a<br />

lower-case s if tl1e lasl argument' was not 1. -@P prints "y" if tl1e argument is L or<br />

"ies"if it is not. -:@P docs the same thing. hut backs up first.<br />

Example:<br />

(format nil "-0 Kitt-:@P" 3) => "3 Kitties"<br />

-* -* ignores one argo -11* ignores the next n arguments. 11 may be negative. -:*<br />

backs up one arg~ - n:. backs up 11 args.<br />

-1l@. is an "absolute gOlO": it "goes to" the 11th argument.<br />

This directive only affects the "loc<strong>al</strong>" args. if control is within som<strong>et</strong>hing like -{,<br />

-% Outputs a newline. -11% outputs 11 ncwlines. No argument is used.<br />

-& Performs a fresh-fine on the output stream (page 185). -Il& outputs n-1 newlines<br />

after the fresh-line.<br />

-x Outputs a space. -I1X outputs n spaces. No argument is used. This directive is<br />

changing in COMMON USP to mean "hexidecim<strong>al</strong> output" (done like -0); to g<strong>et</strong> the<br />

effect of the old -X. one can use - T, or some construct utilizing -< or -{,<br />

Outputs a tilde. - n -<br />

outputs II tildes. No argument is used.<br />

-newline<br />

Ti1de immediately followed by a newline ignores the newline and any whitespace at<br />

the beginning of the next line. With a :, the whitespace is left in place. With an @,<br />

the newline is left in place. This directive is typic<strong>al</strong>1y used when a fonnat control<br />

string is too long to fit nicely into one line of the program:<br />

(format the-output-stream "-&This is a reasonably -<br />

long string-%")<br />

which is equiv<strong>al</strong>ent to formating the string<br />

"-&This is a reasonably long string-%"<br />

-I Outputs a fonnfeed. -Ill outputs It fonnfccds. No argument is used.<br />

MC:<strong>NIL</strong>MAN:FORMAT 7<br />

23-DEC-83


Fonnat 190 <strong>NIL</strong> Manu<strong>al</strong><br />

In the current implementation. -I wiJI do som<strong>et</strong>hing like try to clear the screen on a<br />

termin<strong>al</strong>. However. this will be changed: the intent of -I is to output the page<br />

separator character. which might be inconvenient to type in or have sitting in tJle<br />

middle of a fonnat· string in ones source file. To g<strong>et</strong> the old behavior. use<br />

-:I-eventu<strong>al</strong>ly -I will be changed.<br />

- T Spaces over to a given column. The fun fonn is -destillatiol1,illcremel1tT. which wi11<br />

output sufficient spaces to move the cursor to column destinatioll. I f the cursor is<br />

<strong>al</strong>ready past column destination. it will output spaces to move it to column<br />

destilla/ioll + iucrelllellf. k. t(lf the sm<strong>al</strong>lest integer v<strong>al</strong>ue k possible. illcrrmelll d<strong>et</strong>~llIlts<br />

to 1. This is implemented by tJ1C format-tab-to function. pagc IlJ6. On certain<br />

streams. this may not actu'llly Olltput sptlces. but may usc cursor positioning: mus.<br />

one should not depend on -'I' "erasing" text by the typing of spaces.<br />

This will be changed slightly to eliminate a common and unsightly fencepost.<br />

Currently -Twill do nothing if the "cursor" is exactly at column drstill<strong>al</strong>ioll;<br />

however. it will be changed S(l that spacing will be done then too.<br />

In the future. -@T will do relative positioning.<br />

-0 -0 uses one argument. and applies it as a function to params. It could thus be used<br />

to. for example, g<strong>et</strong> a specific printing function interfaced to format without defining<br />

a specific operator for that operation. as in<br />

(format t "-&; The frob -vQ is not known.-%"<br />

~~~~<br />

• • ....,..,<br />

'~~~h_~"~~+~"\<br />

•• Wa.I ,.,•• If "" '- I I<br />

The printing function should obey thc conventions described in section 19.6.2. page·<br />

194. Note mat tJ1C function to -0 follows the arguments it will g<strong>et</strong>, because they are<br />

passed in as format param<strong>et</strong>ers which g<strong>et</strong> collected before the operator's argument.<br />

Not in COMMON I.ISP.<br />

-[ -[SlrO -;5Irl -;•.• -;slrl1-] is a s<strong>et</strong> of <strong>al</strong>ternative control strings. The <strong>al</strong>ternatives (caned<br />

clauses) are separated by -; and the construct is terminated by -]. For example.<br />

"-[Siamese -;Manx -;Persian -;Tortoise-SheU -;Tiger -;Yu-Hsiang -]kitty".<br />

The argth <strong>al</strong>ternative is selected; 0 selects the first. If a numeric param<strong>et</strong>er is given<br />

(Le. -liD. then the param<strong>et</strong>er is used instead of an argument (this is useful only if<br />

the param<strong>et</strong>er is It # It). If arg is out of range no <strong>al</strong>ternative is selected. Aftcr the<br />

selected <strong>al</strong>ternative has bcen processed, the control string continues after the -].<br />

-[SlrO-;slrl -; .•. -;slrn-:;de!au!I-] has a default case. If the lasl -; used to separate<br />

clauses is instead -:;. then the last clause is an "else" clause, which is performed if<br />

no other clause is selected. For example. "-[Siamese -;Manx -;Persian<br />

-;Tortoise-Shell -;Tiger -;Yu-Hsiang -:;Unknown -] kitty".<br />

-[-lagOO,lagOl,... ;slrO-lagIO,•.. ;5Irl... -] <strong>al</strong>lows the clauses to have explicit tags. The<br />

param<strong>et</strong>ers to each -; arc numeric tags for the clause which follows it. That clause is<br />

processed which has a tag matching the argument. If -:<strong>al</strong> ,a2 ,bl ,b2,... ; is used, then<br />

the fol1owing clause is ~1gged ilOt by single v<strong>al</strong>ues but by ranges of v<strong>al</strong>ues <strong>al</strong> through<br />

a2 (inclusive), bl through b2, ctc. -:; with no param<strong>et</strong>ers may be used at the end<br />

to denote a default clause. For example. n_[";"+,'-,'.,'II;operator -'A,'Z,'a,'z;l<strong>et</strong>ter<br />

-'O,'9;digit -:;other -)".<br />

MC:NII.MAN:FORMAT 7<br />

23-DEC-83


Nil. Manu<strong>al</strong> 191 Format<br />

-:[jil/sr-;Irur-] selects the ]iI/SC control string if arg is nil. and selects the Ime<br />

control string otherwise.<br />

-@[lfUr-] tests the argument. If it is not nil. then the argument is not used up.<br />

but is the next one to he processed. and the one clause is processed. I f it is nil. then<br />

the argument is used up. and the clause is not proccssed.<br />

(s<strong>et</strong>q prinlevel nil prinlength 5)<br />

(format nil "....@[<br />

PRINlEVEl=-D-]-@[ PRINlENGTH=-D]"<br />

prinlevel pr.inlength)<br />

=> "PRINlENGTH=5"<br />

-R If there is no param<strong>et</strong>er. thcn arg is printed as a cardin<strong>al</strong> English nllmh~r. e.g. four.<br />

With the colon modifier, arg is printed as an ordin<strong>al</strong> number, e.g. fourth. With the<br />

atsign modifier. arg is printed as a Roman numer<strong>al</strong>. e.g. ) V. \Vith hoth atsign and<br />

colon. arg is printed as an old Roman numer<strong>al</strong>. c.g. 1111.<br />

I f there is a param<strong>et</strong>er. tilen it is the radix in which to print the number. The flags<br />

and any remaining param<strong>et</strong>ers arc used as for tile -0 directive. 1ndced, -0 is the<br />

same as -10R. The full fonn here is therefore -radix,millco/,pacichar,co1l1mocharR.<br />

-C arg is coerced t(~ a character code. With no modifiers, -C simply outputs this<br />

character. -@C outputs the character so it can be read in again using the # reader<br />

macro: if there is a named character for it. that will be used, for example<br />

It # \R<strong>et</strong>urn": if not. it will be output like "# / Alt. -:C outputs the character in<br />

- justifies le:,.-I within a field millca! widc. lexl<br />

may be divided up into segments with -;-the spacing is evenly divided b<strong>et</strong>ween the<br />

text segments. \Vith no modifiers. the leftmost text segment is left justified in the<br />

field. and me rightmost text segment right justified: if there is only one. as a speci<strong>al</strong><br />

case, it is right justified. The colon modifier causes spacing to be introduced before<br />

MC:NII.MAN:FORMAT 7<br />

23 .. DEC-83


Fonnat 192 <strong>NIL</strong> Manu<strong>al</strong><br />

the first text segment: the atsign modifier c<strong>al</strong>lses spacing to he added aner the last.<br />

millfJcld. default D. is the minimum Ilumoer of fJd(leliar (def~llllt space) padding<br />

characters to he output b<strong>et</strong>ween each segment. I f the to~lI width needed to satisfy<br />

these constraints is greater than minco/. then millco/ is adjusted upwards in co/inc<br />

increments. co/im· defaults to 1. For example.<br />

(format nil "-lO") => "foo bar"<br />

(format nil "-lO:") => " foo bar"<br />

(format nil "-lO:@") => " foo bar"<br />

(format nil "-lO") => " foobar"<br />

(format nil "-lO:@") => " foobar "<br />

(format nil "$-10... ·." 2.59023)<br />

=> "$•••••• 2.59"<br />

If -" is used within a -< construct. then only the clauses which were compl<strong>et</strong>ely<br />

processed arc used. For example.<br />

(format nil "-15" 'fool<br />

=> " FOO"<br />

(format nil "-15" 'foo 'bar)<br />

=> "FOD BAR"<br />

(format nil "-15" 'faa 'bar 'baz)<br />

=> "FOD BAR SAZ"<br />

If the first clause of a -< is tenninated with -:; instead of -;, then it is used in a<br />

spcd'11 wa:i. All Gf the dau5c5 an: pilJ\:c:i5\:d (suh.i(ct ill -'. uf \.:OUi~C). hut un: fif~i.<br />

one is omitted in performing the spacing and padding. When the padded result has<br />

been d<strong>et</strong>ennined. then if it will fil on the current jine of output, it is output. and the<br />

text for the first clause is discarded. If. however. the padded text wi11 not fit on the<br />

current Jine. then the text for the first clause is output before the padded text. The<br />

first clause ought to contain a carriage r<strong>et</strong>urn. The first clause is <strong>al</strong>ways processed,<br />

and so any arguments it refers to wi1l be used; thc decision is wh<strong>et</strong>her to usc the<br />

resulting piece of text. not wh<strong>et</strong>her to process the first clause. If the -:; has a<br />

numeric param<strong>et</strong>er n, then the padded text must fit on the current line with n<br />

character positions to spare to avoid outputting the first c1ause's text. For example,<br />

the control string<br />

"-% 0" .. -{-


<strong>NIL</strong> Manu<strong>al</strong> 193 Fonnat<br />

-{Sfr'" }<br />

This is an iteration constnlct. The argument should be a list which is used as a s<strong>et</strong><br />

of arguments as ·if for a recursive c<strong>al</strong>l to format. The string Sfr is used re.pcatedly as<br />

the control string. Each iteration can absorb as many clements of the list as it likes.<br />

If before any iteration step the list is empty. then the iteration is tenninated. Also. if<br />

a numeric param<strong>et</strong>er n is given. then there will be <strong>al</strong>most II repctitions of processing<br />

of sir.<br />

-:{str-} is similar. but the argument should be a Jist of slIblists. At each rep<strong>et</strong>ItIon<br />

step one slIbtist is lIsed 415 the s<strong>et</strong> of arguments fbr processing sIr: on the next<br />

rep<strong>et</strong>ition a new slIbJist is uscd. wh<strong>et</strong>her or not an of the lastsuhlisl had heen<br />

processed.<br />

-@{Slr-} is similar to -{slr-}. but instead of using one argument which is a list.<br />

<strong>al</strong>l the remaining arguments are used as the list of arguments for the iteration.<br />

-:@{Slr-} comhines thc features of -:{sfr-} and -@{sfr-). 1\11 the remaining<br />

arguments are used. and each one must be a list. On each iteration one argument is<br />

used as a list of arguments.<br />

Terminating the rep<strong>et</strong>ition construct with -:} instead of -} forces sIr to be processed<br />

at least once even if the initi<strong>al</strong> list of arguments is null (however. it will not override<br />

an explicit numeric param<strong>et</strong>er of zero).<br />

If sir is null. then an argument is used as sIr. }tmllst be a string. and precedes any<br />

arguments processed by thc iteration. As an example, the following are equiv<strong>al</strong>ent:<br />

(apply (function format) (list- stream string args»<br />

(format stream "-1{-:)" string args)<br />

rll1is will usc string as a fonnatting sU'ing. lbe -1 { says it will be processed at most<br />

once. and the -:} says it will be processed at least· once. Therefore it is processed<br />

exactly once, using args as the arguments.<br />

-} Terminates a -f. It is undefined elsewhere.<br />

- A This is an escape construct If there are no more arguments rcmammg to be<br />

processed. then the immediately enclosing -{ or -< construct is terminated. (In the<br />

latter case. the -< formatting is perfonned. but no more clauses are processed before<br />

doing the justification. The _A should appear only at the beginnillg of a -< clause,<br />

because it aborts the entire clause. It may appear anywhere in a -{ construct) If<br />

there is no such enclosing construct. then the entire fonnatting operation is<br />

tcnninated.<br />

If a numeric param<strong>et</strong>er is given~ then tennination occurs if the param<strong>et</strong>er is zero.<br />

(Hence _A is the same as- # A.) If two param<strong>et</strong>ers are given. tennination occurs if<br />

they arc equ<strong>al</strong>. If three are given. tennination occurs if the second is b<strong>et</strong>ween the<br />

other two in ascending order.<br />

If - A is used within a -:{ construct. thcn it merely tcnninates the current iteration<br />

step (because in the standard case it tests for remaining arguments of the current step<br />

only); the next iteration step commences immediately. To tcnninate the entire<br />

MC:<strong>NIL</strong>MAN:FORMAT 7<br />

23-DEC-83


Fonnat 194 <strong>NIL</strong> MC:tnu<strong>al</strong><br />

iteration process. use -: A<br />

•<br />

-IIG This is the old fonn of -n@.. above. In COMMO~ I.1SI>. -G is a floating-point<br />

fonnat directive derived from I·URTRAN G fonn<strong>al</strong>. New code should use -@ •.<br />

-F Reserved for fixcd.;field floating-point fonnat.<br />

-E Reserved for exponenti<strong>al</strong> floating-point fi)rmat.<br />

-$ This is 1101 y<strong>et</strong> defilled ill N 1'-<br />

- rdig .ldig jir/d,ptldclwr$ prints arg. a flunum. with exactly rdi/!. digits after the<br />

decim<strong>al</strong> point. The def4tull for rtit!!, is 2. which is convenient fill" printing "mounts of<br />

money. At least /dip, digits will be printed prel'eding the decim<strong>al</strong> point: leading zeros<br />

will be printed if there would be fewer thanldig. The default for ldig is L The<br />

number is right justified in a field /irld columns· long. padded out with padehar. The<br />

colon modifier means that the sign character is to be at the beginning of lhe field.<br />

before the padding. rather than just to the left of the number. 'Inc atsign modifier<br />

says th<strong>al</strong> the sign character should <strong>al</strong>w~ys be output.<br />

In some implementations. if arg is unreason~lbly large. it will be printed in<br />

-field."padchar@A format: i.e. it will be prine'cd right-justified in the specified field<br />

width. This wi11 not happen in the Maclisp implementation, because the range<br />

provided by Honums is not extremely large.<br />

- \ This is not rc<strong>al</strong>ly an operator. If one desires to use a multi-character format operator,<br />

it may oe piaced within baCk siash es, as In -\now\ tor tile now operator. See page<br />

188.<br />

19.6.2 Defining your own<br />

Everything in this section is defined in the MACL1SP and <strong>NIL</strong> implementations of format only.<br />

d<strong>et</strong>1ne-tormat-op<br />

This may be used in two fonnats:<br />

(defi ne-format-op operator varlist body-forms. .• )<br />

and<br />

(defi ne-format-op operator character)<br />

The operator may be a character. suing. symbol. or fixnum code for a character (in <strong>NIL</strong>,<br />

it is coerced using the string function. page 112). Whichever, it is canonic<strong>al</strong>ized (into<br />

upper case) and will be interned into the same package which format resides in. For<br />

example. the format operator for tilde could be defined as<br />

(define-format-op \- '\-)<br />

For the first format. the type of operator is d<strong>et</strong>ennined by decoding varlis!, which may<br />

have one of the following formats:<br />

(params-var)<br />

An operator of exactly zero arguments; params-var will g<strong>et</strong> bound to the<br />

param<strong>et</strong>ers list<br />

(params-l'ar arg-vary<br />

An operator of exactly one argument; params- var will g<strong>et</strong> bound to the<br />

MC:<strong>NIL</strong>MAN;FORMAT 7<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 195 Fonnat<br />

param<strong>et</strong>ers list. and arg- var to the argument.<br />

(params-var . args-var)<br />

An operator of a variable number of args: paramS-l'ar will g<strong>et</strong> bound to the<br />

param<strong>et</strong>ers list. and args-var to the remaining arguments to format (or to the<br />

recursive -{ arguments). The operator should r<strong>et</strong>urn as its v<strong>al</strong>ue some sublist<br />

of args-l'ar, so that format knows how many were used.<br />

A definition for the appropriate function is produced with a bvl derived from the variables<br />

in varUst and a body of body-forms. (The argument ordering in the function produced is<br />

compatible with that on the l.isp Machine. which is arg-l'ar (if any) first, and then<br />

params-var.)<br />

standard-output<br />

Variable<br />

Output from format operators should be sent to the stream which is the v<strong>al</strong>ue of<br />

standard - output.<br />

format: eo 1 on-f1 a9<br />

Variable<br />

format:ats1gn-flag<br />

Variable<br />

These tell wh<strong>et</strong>her or not we have seen a colon or atsign respectively while parsing the<br />

param<strong>et</strong>ers to a format operator. They are only bound in the toplcvel c<strong>al</strong>l to format, so<br />

are only re<strong>al</strong>ly v<strong>al</strong>id when the format operator is first caned: if the operator does more<br />

param<strong>et</strong>er parsing (like -[ does) their v<strong>al</strong>ues should be saved if they will be needed.<br />

Tne params are passed in as a iist ThIS iist. however, may be temporary storage only: one<br />

should not <strong>al</strong>low it to be "passed back" from the c<strong>al</strong>l to the fonnat operator without being copied<br />

first Also, it is recommended that fonnat params be referenced with elt, and their length<br />

obtained with length, in order that they may be reimplemcnted as some sort of sequence in' the<br />

future (which will probably be a stack-<strong>al</strong>located vector for <strong>NIL</strong>).<br />

Conceptu<strong>al</strong>ly, format operates by perfonning output to some stream. In practice, t.his is what<br />

occurs in most implementations; in Mac1isp, there are a few speci<strong>al</strong> SF As used by format. This<br />

may not be possible in <strong>al</strong>l implementations, however. To g<strong>et</strong> around this, format has a<br />

mechanism for <strong>al</strong>lowing the output to go to a pseudo-stream, and supplies a s<strong>et</strong> of functions<br />

which will interact with these when they are used.<br />

format-tyo character<br />

tyos character to the format out.put destination. character may be either an object of type<br />

character, or the fixnum code for a character.<br />

format-prine object<br />

princs objecl to the format output destination.<br />

format-pri n1 object<br />

prin 1 s frob to the format output destination.<br />

MC:<strong>NIL</strong>MAN:FORMAT7<br />

23-0EC-83


Format 196 <strong>NIL</strong> Manu<strong>al</strong><br />

format-lcprinc string capit<strong>al</strong>ize?<br />

This outputs sIring. which must be a string or symbol. to the format output destination<br />

in lower-case. 1f capit<strong>al</strong>ize? is not nil, then the first character is converted to upper case<br />

rather than lower.<br />

format-terpri<br />

Docs a terpri to the format output destination.<br />

format-charpos<br />

format-linel<br />

R<strong>et</strong>urn the charpos and linel of the format output destination. Since in the MACI.lSP<br />

implementation multiple output destinations may be implicitly in use (via outfiles, for<br />

instance). this attempts to choose a representative one. The tennin<strong>al</strong> is preferred if it is<br />

involved.<br />

format-fresh-line<br />

This performs the fresh-line operation ~o the default format destination. 'The hair<br />

involved in this is mostly subsumed by the fresh-line function in NIl.<br />

for.nat- tab -to destillation &option<strong>al</strong> increment<br />

rIbis implements - T to the current format destination (q.v.). In <strong>NIL</strong>, it wi1l utilize the<br />

:tab-to message if that is supported. Otherwise. if it can d<strong>et</strong>ermine the "current position"<br />

of the format destination. it will output the proper number of spaces; <strong>al</strong>l else failing, two<br />

~paC'~C\ will hp output.<br />

format-formfeed<br />

Performs a formfeed on the format output destination. In <strong>NIL</strong>, this will send the'<br />

:formfeed message to the stream if that is supported. the :clear-sereen message if that is<br />

supported, otherwise just output the page separator character. The :formfeed message is<br />

supported by a number of <strong>NIL</strong> streams, and is designed for just this use.<br />

format-flatc<br />

(format-fl ate IannI lann2 ... fonnn)<br />

The fonns are ev<strong>al</strong>uated in . an environment similar to that used inside of format: the<br />

various format output-performing routines such as format-tyo and format-prine may be<br />

used to "perfonn output". In <strong>al</strong>l but the MULTICS MACLISP implementation, standardoutput<br />

will be a stream which simply counts the characters output-it will only support<br />

the :write- char operation.<br />

MC:NJLMAN:FORMAT 7<br />

23-DEC-83


ifSY'· '''7<br />

r • M<br />

ttntn .,<br />

<strong>NIL</strong> Manu<strong>al</strong> 197 Querying the User<br />

19.7 Querying the User<br />

The following routines are built on the fquery function, which is modeled after that of LISP<br />

~1ACIIl~E LISP. fquery is complicated and subject to change, however, and is not jtself<br />

documented here. Of the following routines, y-or-n-p and yes-or-no-p are defined by<br />

C07\1~10~ LISP: the others are not.<br />

y-or-n-p &option<strong>al</strong> message stream<br />

This prints message to stream (which defaults to the v<strong>al</strong>ue of query-io), and then reads a<br />

character from stream. It r<strong>et</strong>urns t or nil depending on wh<strong>et</strong>her the character signified a<br />

posllIye or negative response: space and rllbollt are accepted in place of y and n.<br />

Because it is so easy to gel a mistaken response fhnn this routine. it should be lIsed for<br />

anticipated questions only.<br />

Because it is used for both input and output, Siream must be bi-direction<strong>al</strong>.<br />

yes-(,.'-no-p &option<strong>al</strong> message stream .<br />

This is similar to y-or-n-p. but requires a more compl<strong>et</strong>e answer. Typeahead to stream<br />

is flushed (with clear-input. page 183), and it feeps. before rcading a compl<strong>et</strong>e "yes" or<br />

"no" followed by a new1ine.<br />

format-y-or-n-p jhmuJ/-slrill1!, &rcst jiJnl1<strong>al</strong>-args<br />

Most the time when y-or-n-p is used, people seem to want to lise a fonnat string with<br />

some arguments. This docs that. Input and Olltput is done to query-ia. Otherwise. it<br />

behaves like y-or-n-p.<br />

format-yes-or-no-p fonnat-string &rcst fomrat-args<br />

Similar.<br />

19.8 Filesystem Interface<br />

The <strong>NIL</strong> filcsystem interface is designed to <strong>al</strong>low it to refer to more than one filesystem. The<br />

names of files are not represented as just strings· or lists of components. but are objects of type<br />

pathname. The pathname objects for different filesystems or hosts would be of different types,<br />

and operations on files in the filesystem are perfonned with respect to that type. For instance. we<br />

have under development facilities to <strong>al</strong>low use of the filesyslems of TOPS-20 and ITS through<br />

CHAOS~ET. At the moment, only the loc<strong>al</strong> VMS filcsystem is supponed.<br />

MC:NII MAN:NEWIO 27<br />

23-DFC-83


Filcsystelll Interface<br />

198<br />

19.8.1 Pathnames<br />

A pathname has six criteri<strong>al</strong> components.<br />

host<br />

This component <strong>al</strong>ways contains an object which describes the filesystem the pailiname<br />

refers to. 1\11 pathnames have such a component: no pathname may be fonned without<br />

such a component. 'l1lUs, pathname interpr<strong>et</strong>ation is <strong>al</strong>ways performed with respect to<br />

some host.<br />

device<br />

This is nonn<strong>al</strong>1y a string. naming a device.<br />

directory<br />

1\ string naming a dirC'ctory. or a list of strings. if the directory is structured (that is. if<br />

the pathname is in a subdirectory).<br />

name<br />

/\ string. the "primary" or· "root" name of the file.<br />

type<br />

1\ string. thC' "type" of the file. This is not necessarily as tJle C'x/C'lIsion which wil1 be<br />

used to fonn the host~specific pathname string~ e.g., for a VMS filesystem. a file type of<br />

LIS P corresponds to the C'xtension LS P.<br />

version<br />

Thi~ i~ th(' v('~inn nf tht' pathl1atTl~: H!m~Hy it is an integer.<br />

1\ p<strong>al</strong>hname need not refer to an actu<strong>al</strong> file in a filesystem. nor need <strong>al</strong>l the components<br />

(other than the host) be present. An unspecified component is represented by nil. Such a<br />

component may be supplied by later defaulting operations. Components may <strong>al</strong>so contain certain<br />

keywords which arc interpr<strong>et</strong>edspcciaUy:<br />

:wifd<br />

A "wildcard" component.<br />

: newest<br />

:oldest<br />

These are only applicable to the version component of a pathname. They cause the<br />

reference to the filesystem to refer to the newest or oldest version present Only : newest<br />

is actu<strong>al</strong>ly supported by the VMS filesystem interface.<br />

:unspecific<br />

I f any component in a pathname has this as its v<strong>al</strong>ue. then the pathname does not refer<br />

to a specific file in the filesystem~ but rather to the group of files which match the other<br />

components. This is nonn<strong>al</strong>ly only used for the type or version components. so that one<br />

may refer to the entire group of files with the same device. directory, and name. This<br />

docsn °t have any use in <strong>NIL</strong> y<strong>et</strong>; when ~}L pathnames gain the ability to have arbitrary .<br />

attributes (properties) associated with them, it will be significant.<br />

:implied<br />

I f a path name has this as a componC'nt. it means that the device component is a logic<strong>al</strong><br />

name which will supply the v<strong>al</strong>ue for that component l11is is llsed as a pbceholder for<br />

"pathname merging tt • All components other than the host and device components may<br />

MC:NII.Mi\N:NEWIO 27 23~I)EC .. 83


a'TSSr<br />

Sf tin<br />

<strong>NIL</strong> Manu<strong>al</strong> 199 Fi 1csystem 111 terrace<br />

wke on this as their v<strong>al</strong>ue.<br />

:relative<br />

This can only occur within a structured directory component. It is used in the<br />

representation of VMS rooted directories. For instance, the V\1S pathname<br />

_DBAO: [N I l259 .] parses into a pathname with the string "__ DBAO" as its device<br />

component. and the list (" NI l259" . : re 1 at; ve) as its directory component. <strong>NIL</strong><br />

uses this in pathname merging.<br />

:elipsis<br />

This is used in representing things like nil $ d; s k : [n i 1 ... ].<br />

pathname \,,:mlld produce a directory component of ("NI L" .<br />

prohably be flushed in t~lvor of utilizing just :wiJd instead.<br />

Parsing that into a<br />

:elipsis). It will<br />

19.8.1.1 Pathname Functions<br />

pathname thing<br />

thing is coerced into a pathname.<br />

If it is a pathname, it is r<strong>et</strong>urned.<br />

If it is a list. then it is assumed to be a \L\CI lSi> namc1ist: interpr<strong>et</strong>ation of this, and<br />

MACl.IS}> compatible pathname handling. is discussed in


Filcsystem Interface 200 N II. Manu<strong>al</strong><br />

Under VMS, this is obtained by translating the logic<strong>al</strong> name SYSSLOGIN.<br />

user-work.1 ngd i r- pathname &oplion<strong>al</strong> host<br />

R<strong>et</strong>urns the user's working direclory, as a pathname:<br />

components will be unspecified.<br />

the name, type, and version<br />

For V\1S.<br />

this is obtained from the RMS default directory string. and the 5YS$O 15K<br />

logic<strong>al</strong> name. Note that the RMS default is copied from the command interpr~ter when<br />

the !"II process is created: temporarily exiting the !\H. and changing the default wiH 110t<br />

change the v<strong>al</strong>ue of this.<br />

user-scratchd 1 r- pathname &option<strong>al</strong> host<br />

R<strong>et</strong>urns, as a p<strong>al</strong>hnamc, the directory of the directory which should be used hy programs<br />

for writing "scratch" fiJes.<br />

The loc<strong>al</strong>-vms host uses the v<strong>al</strong>ue of the logic<strong>al</strong> name SYS$SCRATCH if th<strong>al</strong> exists.<br />

otherwise the user's home directory. If for some reason the device field is absent<br />

SYS$OISK is supplied. Note that the v,.lue of the logic<strong>al</strong> name is copied from the<br />

command interpr<strong>et</strong>er when the 'II is created. Temporarily exiting from the 'II "nd<br />

changing the logic<strong>al</strong> name definition will have no effect.<br />

1 n 1 t - f 11 e - pat h name program-name &option<strong>al</strong> host<br />

This r<strong>et</strong>urns the pathn


<strong>NIL</strong> Manu<strong>al</strong> 201 FilcsySlclll I ntcrfacc<br />

perfonned, such as pathname parsing.<br />

merge-pathname-defaul ts pathllame &option<strong>al</strong> defaults de/aul!-Iype defoul!-version<br />

lbis is the main merger. p<strong>al</strong>hname may be anything coercible to apathname. defaults<br />

may be a pathname defaults object. a path name. or a string or symbol (which will be<br />

coerced to a pathname first). de/aull-type and de/aull-version may be whatever is <strong>al</strong>lowable<br />

for types and versions.<br />

If it is necessary. p<strong>al</strong>hname will be, parsed with respect to a host d<strong>et</strong>cnnined from<br />

de/aults. If the directory field of it is missing. then that wiJI be supplied by de/aults.<br />

Therc is somc qucstion as to what shollld happcn if thc dcvicc field of p<strong>al</strong>llllOll1e is<br />

Il1ISSl11g: cllrrcIllI~. it b simpl~ filled in from I.I£:t,'wlls. In the I -isp Machine<br />

implcmcntation of this function. it is supplied as thc dcf;llIlt dcvicc for thc host (perhaps<br />

inconsistcntly. for instance only when parsed from a string?): probably what should<br />

happen is that wh<strong>et</strong>hcr the devicc comcs from de/ilulls or not is dctcrmincd by thc host.<br />

so that it would if thc dcvices wcre re<strong>al</strong>ly structured (with directories in them <strong>et</strong>c.). and<br />

would not otherwisc (wh.ch in I -isp Machine l.isp appears to he mainly for the sake of<br />

the ITS operating system).<br />

If p<strong>al</strong>/mOille has a name supplied, then if the type and version of the resuning pathname<br />

are defaultcd from de/aull-type and default-version, as necessary. Otherwise, the name.<br />

type. and version are defaulted from dc/aulls. Thus:<br />

(merge-pathname-defaults<br />

"[nil.vaz]fcc" "zyz$disk:[gzb]zz.1:;p:3" "'f .. ,.. 1 " ,<br />

" ... .,) I J<br />

, => #<br />

(merge-pathname-defaults<br />

"[nil.vas]" "sysSdisk:[gsb]zz.lsp;3" "vasl")<br />

=> # #<br />

In the above, it is worth noting that It =" as a pathname component is used as a<br />

placeholder for an unspecified component, and that a file type of lisp is mapped (by the<br />

VMS pathname code) into an extension of Isp, and vas I to vas. The specifics of the<br />

syntax and file-type/extension mapping are described elsewhere.<br />

The default v<strong>al</strong>ue of default-version is :newest. The default v<strong>al</strong>ue of default-type is "lisp";<br />

however, it is highly recommended that this not be depended upon, as it may be changed<br />

to come from defoults.<br />

Here are some of the pathname defaults in use in <strong>NIL</strong>.<br />

-1 oad-pathname-defau1 ts* Variable<br />

This is used to provide pathname defaults for load, compile-file, and any similar<br />

functions. It is initi<strong>al</strong>ized to the user's working directory with name F 00 and type lIS P<br />

(sec user-workingdir-pathname. page 200).<br />

MC:<strong>NIL</strong>MAN:NEWIO 27<br />

2J-DEC-83<br />

-: "" " ":;;.;.>, .;: ", "'.' , "<br />

'':''~: ". ' .. - . i,~ ",- ';'.~-: "" '--.. '..,,',:' " -- .. - , . "-"


FHt'system Interface . 202 Nil. Manu<strong>al</strong><br />

*defaul t-pathname-d<strong>et</strong>aults.<br />

Variablf<br />

This provides super-defaults for anything that needs them. such as open. with-open-file,<br />

and parsing a pamname· string out of context. It is initi<strong>al</strong>ized to the user's working<br />

directory with name FDD and type LISP (see user-workingdir-pathname. page 200) ..<br />

*scratch-pathname-dataul ts*<br />

Variable<br />

This is used by things which must write out "temporary" files. Things which use this<br />

should not modify it: it should be left to the user to s<strong>et</strong> default pathnames for hosts<br />

(primarily for the sake of the device and directory) to say where such files should be<br />

written. See user-scratchdir-pathname. page 200.<br />

For example. the current '" compile function creates a file named aaafoo.vas. and<br />

supplies the de\icc and directory from *scratch - pathname-defaults*.<br />

19.8.2 Opening Files<br />

Files arc opened with the open function (page ISO). or with-open-fite (page 181). and may<br />

he dosed wilh~lose (rage 181). open hy default assumes that the open is a reference to a file.<br />

so coerces its fit st argument to a pathname. and then creates a Slre~lln to the specified file in the<br />

filesystem. <strong>NIL</strong> currently employs only two modes of file opening. These are :ascii and :byte<br />

modes.<br />

:asc;j will cause the file to be written as variable-length records. with record-attribute of<br />

carriage-r<strong>et</strong>urn. The existing disk 1/0 code docs not have the intelligence to de<strong>al</strong> with records<br />

longer than 512 hytes. however. so is forced to tenllinatc records when that limit is reached. To<br />

compensate. so that spurious newlines do not g<strong>et</strong> inserted into LISP files. recordsexactJy 512 long<br />

arc assumed to not actu<strong>al</strong>ly be tcnninated. but "continued tt with the next record. when read as<br />

input<br />

:fixnum simply uses fixed-length S12-byte records; this is what vas 1 files use.<br />

fs:close-<strong>al</strong>'-f1'es<br />

In case you do mess up and lose track of some files, this will close <strong>al</strong>l open files (which<br />

have been re<strong>al</strong>ly opened as streams, not just kludgey temporary opens). Every known<br />

host object is supposed to keep track of <strong>al</strong>l streams which it has open. in such a way as<br />

to be secure against timing screws, so that this may at least be done.<br />

Doing (exhibit fs:.host-instances*) should give one a handle on the open files, as the<br />

host instances should point to the filcs they have open. fs:*host-instances* is the list of<br />

<strong>al</strong>l known hosts, and is used to (among other things) drive host-name lookup.<br />

MC:NII.MAN:NEWIO 27<br />

23-1)J-=C-83


~II. Manu<strong>al</strong> 203 Fiksyslcm Intcrface<br />

19.8.3 Other File Operations<br />

probe-f11 e p<strong>al</strong>hname<br />

If p<strong>al</strong>hname (which is coerced to a pathname with the pathname function) can be opened,<br />

its truename is r<strong>et</strong>urned; otherwise. nil is r<strong>et</strong>urned. This may be used to see if p<strong>al</strong>hname<br />

exists and is accessible. (If a file protection error occurs, probe-file r<strong>et</strong>urns nil, <strong>al</strong>though<br />

that may change. as the intent is to see if the file exists.)<br />

~ote file-length and filepos are missing from <strong>NIL</strong><br />

All of the remaining functions in this scction de<strong>al</strong> with either a strcam. or with a pathname.<br />

ror thc fi.mll cr. thc) perform the operation Oil thc open strcam: f(lr the 1.mcr. on the ilk in the<br />

filcsystcm. which may invohc opcning the file tcmporarily. At present. nonc of thcm work on<br />

streams. A futurc edition of the filesyslem code will contain more code written in IISP. and be<br />

much more versatile in this regard.<br />

For the fut ..:tions which arc dcscribed as rcturning an error description. this is prohahly a<br />

string. but may changc to be a more complicated object in the future. (That objcct should.<br />

howc\cr. h


Filcsys(em Interface 204 <strong>NIL</strong> Manu<strong>al</strong><br />

19.8.4 File Matching<br />

<strong>al</strong>l files list-ofpathnames<br />

Rcturns a list of pathnamcs matching <strong>al</strong>l of those in Iist-ofpafhnames. This is done. of<br />

coursc. by appending tog<strong>et</strong>her the lists of pathnames which match each of the pailinames<br />

in list-ofp<strong>al</strong>hllames.<br />

By convcntion. this matches over <strong>al</strong>l those components not specificd in each pathname.<br />

V\1S docs not <strong>al</strong>low matching <strong>al</strong>l devices. howevc('. so the device should be specified. or<br />

will be defaulted from somewhere (where? rms dcfault but it shouldn't be). Newest<br />

\ersinns can be matched <strong>al</strong>so. by lIsing the appropriate patJlname synt~tx. Note that clipsis<br />

spccifk<strong>al</strong>ions in directories. and star spccificati(}n~ in names. <strong>al</strong>l work (ft,rtuittlllsiy.<br />

p('rhap~. hu( Lhey work): e.g .. (aUfUes "[nil...]286*.*:'" r<strong>et</strong>urns a list (If pathnamcs of<br />

tJle files with highest version number of· a1lthe files in the 'II. hierarchy with first three<br />

char~lclers of their namc being "286".<br />

mapa 11 files jUllctioll Iist-(~r-pathllC1mes<br />

C<strong>al</strong>ls fUllctiol1 on each pathnamc whkh matches pathnamcs in list-ofp<strong>al</strong>hllames. 'lois is<br />

esscmi,llIy equiv<strong>al</strong>en( to<br />

(mapc jUl1cliull (a 11 fi 1 as Iisf-o.fp<strong>al</strong>lllloml's»<br />

but c<strong>al</strong>Js junction on each as it is generated rather than consing up the list<br />

In fact. atlfiles is imp1emented in tenns of mapaJlfiles.<br />

map<strong>al</strong>ffires (and hence <strong>al</strong>lfiles) accept a single symbollstring/pathname in place of a list It is<br />

unclear what should be done about this: it is (currently at least) of no usc to <strong>NIL</strong> to de<strong>al</strong> with<br />

multiple specifications at oncc. and in fact· the origin<strong>al</strong> aU files function in MULTICS MACLISP did<br />

not· takc a list. but only a single pathname.<br />

There is <strong>al</strong>so no kludgy testing in <strong>NIL</strong> such that if a namelist is specified it must be a fullyspccified<br />

nameHst (insofar as explicit "*" components arc spccified). Thus using a namclist as a<br />

single pathname will be interpr<strong>et</strong>ed as a list of pathnames. potenti<strong>al</strong>ly resulting (incorrectly) in a<br />

match over <strong>al</strong>l the files on the current device... (That was the reason for the ,k,ludgey check in<br />

MACUSP. you see ... )<br />

19.8.5 Loading Files<br />

load filename &key :verbose :package :s<strong>et</strong>-default-pathname :static :default-pathname<br />

:characters :binary :defaufts :print<br />

:verbose<br />

Boolcan: print out lots of gubbish about loading. Default is v<strong>al</strong>ue of *Ioadverbose-.<br />

:package<br />

override the package specification (if any) obtained. from the file.<br />

:s<strong>et</strong> -default - pathname<br />

Boolean: s<strong>et</strong> the default p<strong>al</strong>hname of the pathnamc-defaults used (see :defaults<br />

and :defauft-pathname. below). Default is v<strong>al</strong>ue of *Ioad-s<strong>et</strong>-default-<br />

MC:NII.MAN:NEWIO 27<br />

23-I)EC-83


.-<br />

I\ II. Manu<strong>al</strong> 205 File~yslell1 Interface<br />

pathname •.<br />

:defaults<br />

Specified pathname-defaults to use in place of the v<strong>al</strong>ue of .Ioad-pathnamedefaults..<br />

(1bis one isn't in COM:vtO~ LISP. Not clear it should be heavily used,<br />

but i can see it has application.)<br />

:default-pathname<br />

Use this for defaulting. in preference to the pathname-defaults. The defaults are<br />

still s<strong>et</strong> in the defaults specified by :defaults (or its absence).<br />

:characters<br />

:binary<br />

Boolean. :binary t implies that the file is a \'ASI. me: :CII:\R:\C ITkS T implies<br />

that the file is LISP text. By default, the file is examined to d<strong>et</strong>ellnine which it is.<br />

And, if no type is specified in filcnamc, first a file with type vast and then a file<br />

with type lisp will be looked for.<br />

:static<br />

Boolean: says to load tile file into the static heap. Default is v<strong>al</strong>ue of .Ioad - instatic<br />

- area •.<br />

:print<br />

Boolean: if not nil. says that the results of ev<strong>al</strong>uation of fonns in the file are to<br />

be printed. Default is nil, and it probably doesn't work anyway: certainly not for<br />

vasl files.<br />

19.8.6 File Attribute Lists<br />

Not too much d<strong>et</strong>ail y<strong>et</strong>... However. it's necessary to use it.<br />

If. on the first line of a source file the characters ft •••"<br />

appear. then the text from the first "•<br />

• _" to the next is parsed as a file attribute /iSI. (Funnyness with multiple lines? Well, anyway, it<br />

works easily on one line.) This text is logic<strong>al</strong>ly a list of keyword/v<strong>al</strong>ue pairs, witiI the v<strong>al</strong>ues<br />

being either single v<strong>al</strong>ues or lists of v<strong>al</strong>ues. The entire construct is made invisible to the<br />

processing language by being placed within its commenting construct<br />

; -.- Mode:Lisp; Package:Compiler; Base:l0; Readtable:<strong>NIL</strong> -.-<br />

might occur as the first line in a <strong>NIL</strong> compiler source file. It says that the mode of the file is<br />

lisp (this being for the benefit of text editors), and that the file should be read and processed in<br />

the compHer package, decim<strong>al</strong> radix, and using the <strong>NIL</strong> readtable. "Lists" of v<strong>al</strong>ues are provided<br />

for by separating the individu<strong>al</strong> items by commas, as in<br />

; -.- Mode:Lisp; LSB:ppdef.pr<strong>et</strong>ty-print-definition -.-<br />

The parsing of tokens in such a construct is pr<strong>et</strong>ty rudimentary and crufty. but essenti<strong>al</strong>ly things<br />

are symbols except for a series of digits (option<strong>al</strong>ly followed by a decim<strong>al</strong> point) which is a<br />

decim<strong>al</strong> integer.<br />

File attributes typicany translate into some speci<strong>al</strong> binding environment needed for the<br />

processing of the file (in some context). '(be following arc pre-defined in <strong>NIL</strong>:<br />

package I'llckagr-namc<br />

The file is processed in the package named package-name.<br />

MC:NII.~1"N:NEWIO 27<br />

23-I)FC-83


Filesystem Interface 206 <strong>NIL</strong> Manu~tl<br />

readtable readlablC'"'lJamp<br />

The file is read in using the readtable named readtable-name.<br />

naming. is dcscribed in section 16.3. page 126.<br />

Syntax. and readtablc<br />

base radix<br />

Binds both the input and output radices. no matter what those damned variables are<br />

named.<br />

radix radix<br />

For those who are confused by base and will be cvcn moreso when the variable is<br />

namcd .base*.<br />

patch-file y('s·0r-110<br />

If yes"or-Ilo is yes (it shouldn"t be specified otherwise). then a variable pruclaiming the<br />

patch-filc-ness of this file is buund. so th~lt various things can see jt and be clc\cr. like<br />

the helpful function which· warns you about rcdcfining a function dcfined by sumcunc elsc<br />

in anothcr file. (said functiun not existing y<strong>et</strong>).<br />

Isb moc/u/r-nnme,s),slem-llt.1me<br />

This is defined by Isn [4]. not NIl. (q.v.).<br />

When a file attribute list c is parsed. the attribute names arc kcywords, and the v<strong>al</strong>ues are<br />

either keywords or intcgers (or lists of keywords or integers).<br />

: f11 e-p 11 st p<strong>al</strong>/mame<br />

If pnf/mnm(> r:m h(' {\p~n~d~ tf1('n this r~tl!ms a d!s~mbodi~d propt'rty list ~':ith the ft!~<br />

attributcs in the cdr. and the lruename of the file in the car. Otherwise. it r<strong>et</strong>urns nil.<br />

This probably should be renamed :file-attribute-list.<br />

fs : proces s .... 1 n -1 oad-env 1 ronment plis! [unct p<strong>al</strong>llllame &rcst args<br />

plis/ should be a parsed file attribute list (with ane\'ell number of clements: the cdr of<br />

what is r<strong>et</strong>urned by the :file-plist message). p<strong>al</strong>hname should be the pathname which the<br />

file attributes were obtained from.<br />

The environment which is specified by that attribute list is established. and then. fimct<br />

c<strong>al</strong>led with arguments of p<strong>al</strong>hname and whatever args were given.<br />

This is what is used by both load. and the compiler. It enables a stable interface to how<br />

bindings and other environment modifications are obtained from the file attributes.<br />

Examination of the source code (the file [<strong>NIL</strong>. IO]PATHN. LSP) will show the convention<br />

which is used for defining addition<strong>al</strong> file attributes. It is basic<strong>al</strong>ly an extension of that defined by<br />

LISP MACI UNE USP.<br />

MC:NII.MAN:NEWIO 27 2] .. DEC .. 83


------------:--:---:-~::::::::_-_-_-_-:::::::::..--:.~.~~IiiI'~.-~:rilllll ·11'_lilt lin.' _sil·__••••<br />

lIf#~~,i~;:h....,~r·,,"-IIIIIIIiIIIiI-... .....<br />

<strong>NIL</strong> Manu<strong>al</strong> 207 Filesystem Interface<br />

19.8.7 Intern<strong>al</strong>s for Vl\1S Record Man~lgement Services<br />

l':II. contains some primitive routines and datastructure definitions with which I/O can be<br />

performed entirely from LISP code. In fact. recently a speci<strong>al</strong>-purpose stream type was written so<br />

that me editor could do very fast record I/O. This is the loc<strong>al</strong>-vms-editor-stream stream,<br />

which is in the source file nil$disk:[nil.io]vloc<strong>al</strong>.lsp, and can serve as an example of<br />

how some of these things arc used. Some of the other primitives which interface to the filesystem<br />

are <strong>al</strong>so written in I.ISP, but arc hidden from the stream code by a function<strong>al</strong> interface~ these arc<br />

in the file nil$disk:[nil.vmlisp]vmsfile.lsp.<br />

19.8.7.1 Data Structures<br />

The dlltastructures lIsed for R\fS fab. rab. nam. and xah hlocks arc <strong>al</strong>l just simple bit vectors<br />

of the appropriate si/e. There arc liSP macros and constants defined to de<strong>al</strong> with them: these<br />

definitions \\ ere generated from the VMS \fD} files. For instance. (si:fac$b_rfm jl~/b) r<strong>et</strong>urns the<br />

record-fomwt field of a fah. (s<strong>et</strong>f (si:fab$b_rlm ii/b) si:fab$c_ var) s<strong>et</strong>s it to the code which says<br />

that the record format is variable-length rec{lrds. Gener<strong>al</strong>l). fields of type byte and word arc<br />

tCtched/s<strong>et</strong> as fiXIlUIllS. longword and quadword fields arc extracted ilHo (freshl~ conscd) simplebit-vectors<br />

of the appropriate length; the s<strong>et</strong>ting operation replaces the bits of the structure (in the<br />

right position) with the bits of the object it is being s<strong>et</strong> to, so the operation is in\'enib1c. See<br />

<strong>al</strong>so the files nil $ dis k : [n i 1 . vm 1 is P ] rms s t r. 1 s p and<br />

nil$disk:[nil.vmlisp]rmssub.ls~<br />

The following routines create these structures:<br />

si:maKe-fab<br />

si:maKe-rab<br />

si:mak,e-nam<br />

s1 :maKe-xab code length<br />

Because xab structures vary, one must specify the xab code and its length. For instance,<br />

(si:make-xab si:xab$c_fhc si:xab$c_fhclen)<br />

creates a xab block used for hacking fi1e header stuff.<br />

Resources are defined for fab, rab, nam, and xab structures:<br />

s1:fab<br />

si:rab<br />

s1:nam<br />

MC:NII.MAN:NEWIO 27


FilcsYS1CIl1 J J1{rrf~lcr<br />

208<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

s 1 : xab code length<br />

Because xab structures can vary in code and length. they must be supplied to the<br />

resource constructor. The appropriate constants are defined. of course. For instance.<br />

(using-resource (si:xab xabdat si:xab$c_dat si:xab$c_datlen)<br />

. . .)<br />

binds xabdat to a xab structure used for obtaining creation and revision dates.<br />

19.8.7.2 Rl\1S and Related I-Iacking<br />

Thr following flln


;\ II. Manu<strong>al</strong> 209 Termin<strong>al</strong> 1/0<br />

51 : rm5$truncrab<br />

51: rm5$update rab<br />

51:rm5$wa1t rab<br />

51 : rm5$read rab<br />

51: rms$5pace rab<br />

51: rm5$wr 1 te rab<br />

51: rm5$enter fab<br />

51: rm5$par5e Jab<br />

51: rm5$remove Jab<br />

51: rm5$rename Jabl Jab2<br />

51:rms$5earch Jab<br />

s 1 : rms Ss<strong>et</strong>dd 1 r lIl'w·dirc('/ory-.\pccijicatioll<br />

R<strong>et</strong>urns. and mayhe updates. the RMS default directory. If ncw-dircctory-spccification is<br />

iii:' ta'ic ~\rs dcf~lilt is nut mGdlfkd: i.lthciWisc. it is SCi to iiCn'-dii t'dUi j -Spn ifiud i(JiJ.<br />

which must be a simple string. This is a fairly direct interface to the SYS$SETDDIR<br />

system service.<br />

If the r<strong>et</strong>urn status is not norm<strong>al</strong> (the v<strong>al</strong>ue of si:rms$_norm<strong>al</strong>). it is r<strong>et</strong>urned in place of<br />

the string.<br />

51: trnlog logic<strong>al</strong>-name<br />

This performs the trnlog system service on the simple string logic<strong>al</strong>-name. It r<strong>et</strong>urns a<br />

simple-string which is the translation, or nil.<br />

19.9 Termin<strong>al</strong> lID<br />

The current ~IL system contains a termin<strong>al</strong> stream which is translates gener<strong>al</strong> operations into<br />

tennin<strong>al</strong>-specific display codes. Characters output to it (via the :write-char message or the writechar<br />

function) arc interpr<strong>et</strong>ed as either display operations (e.g.. carriage-r<strong>et</strong>urn moves the cursor<br />

to the next line or wraps to the top of the screen, and clears the line it moves to). or as graphic<br />

characters (causing certain characters which are 1101 graphic on typic<strong>al</strong> ascii tennin<strong>al</strong>s to to be<br />

printed with cenain conventions). Line wraparound is performed <strong>al</strong>so.<br />

The best way in which this can be accessed is with the cursorpos function. which is M.\CL1SP<br />

compatible. In t:1Ct. the behaviour of the cursorposable tty stream emulates the behaviour of<br />

tennin<strong>al</strong>s under the ITS operating system. down to the lennin<strong>al</strong>-width fencepost bcha\'iour due to<br />

the use of the last column to hold the continuation character. (The "keyword ch~lracter" argument<br />

to cursorpos. as defined by MACLlSP. in fact derives from the second character in the escape<br />

MC:NII.t\1AN:NE\\'IO 27<br />

2.1-{ )1':C-83


Tcrmin4tlilO 210 Nil. Milfludl<br />

sequence used perfonn that cursor operation under ITS. Ah w<strong>et</strong>l.)<br />

cursorpos &option<strong>al</strong> arg/ argl org3<br />

cursorpos is a MACLISP compatibility function. but it offers an interface to the display<br />

tennin<strong>al</strong> code which may be safely and reliably used. Note that the arguments. are<br />

interpr<strong>et</strong>ed in rather strange manners... As a gener<strong>al</strong> rule. cursorp05 is supposed to<br />

r<strong>et</strong>urn nil if it was not capable of perfonning that particular operation on the particular<br />

stream involved, totherwise. It is 1101 the case, however. that it may be used on non~<br />

tennin<strong>al</strong> streams: that is an error.<br />

(cursorpos)<br />

rCl11rn~ the cursor position of termin<strong>al</strong>-io as a pair. (l'crlictll-posilicm. Iwri=ol1l<strong>al</strong>-posilion).<br />

Both positions arc measured zero-origined. from the top-left corner of the screen. nil<br />

should h(' r<strong>et</strong>urned if the stream docs not hme a gener<strong>al</strong>ly mo\ahlc cursor.<br />

(cursorpos "pos hpos)<br />

Positions the cursor of the stream termin<strong>al</strong>-;o at that position. Either vpos or hpos may<br />

be nil. in which case the current v<strong>al</strong>ue is used.<br />

Otherwise. the first arg to cursorpos should be a symbol (or character object). which<br />

may take an addition<strong>al</strong> argument. The case is irrelevant.<br />

C Clears the screen. The cursor moves to the "home" position (top left corner)~ On<br />

a non-display. this outputs a newline .. so <strong>al</strong>ways succeeds.<br />

A Fresh-linc. In this instance. the fresh-line functiun (page ]85) is preferred.<br />

T<br />

Z<br />

ftTop. It The cursor is homed, moved to the topIeft comer.<br />

Home down. Bottom left comer.<br />

L Clear-to-end-of-line. From the current position to the right margin is cleared.<br />

The cursor does not move.<br />

E C}ear~to-end-of-screcn. Current position. to right margin, and <strong>al</strong>l following lines.<br />

are cleared. The cursor does no move.<br />

U<br />

Move Up a line. Wraps around the screen. does not scroll.<br />

o Move Down a line. Wraps around the screen, does not scroll.<br />

F<br />

Move Forward a character position.<br />

S . Move Backward a character position. If at the left margin. effectively does U<br />

then moves to the column to the left of the continuation-character column (i.e.. it<br />

backs up the amount by which the cursor would have moved for a single-position<br />

printing character).<br />

K Erase the character the cursor is over (this would not be the last one typed<br />

nonn<strong>al</strong>1y. see below:)<br />

X B. then K. Simpleminded way to rubout the last character typed.<br />

Hhpos<br />

S<strong>et</strong> the horizont<strong>al</strong> position to hpos.<br />

MC:NII.MAN:NEWIO 27<br />

23;.I)EC-83


NIl. Manu<strong>al</strong> 211 Termin<strong>al</strong> 110<br />

v "pos<br />

S<strong>et</strong> the vertic<strong>al</strong> posilion to vpus.<br />

The insert-line operation<br />

\ The del<strong>et</strong>e-line operation<br />

111e insert-char operation<br />

the del<strong>et</strong>e-char operation<br />

Addition<strong>al</strong>ly, one may specify a stream to cursorpos by giving that as the last argument.<br />

The atom t as a slream means. as with other printing functions. the termin<strong>al</strong> (the v<strong>al</strong>ue<br />

of termin<strong>al</strong>-io). NOle. howe,,' ... that I/O stream a/so lIses the \·,lllIe of termin<strong>al</strong>-io. rather<br />

lh~1Il standard - output. Note <strong>al</strong>so that the f'{mn<br />

(cursorpos • t)<br />

is interpr<strong>et</strong>ed as requesting the cursor position of termin<strong>al</strong> -io: to do a home-up. one<br />

must use some <strong>al</strong>ternate fonn like<br />

(cursorpos 'top)<br />

(cursorpos #\t)<br />

(cursorpos 't 't)<br />

This strangeness is <strong>al</strong>so \1:\CLlSP compatible ...<br />

19.9.1 l\'Iodifying the Termin<strong>al</strong> Characteristics<br />

s<strong>et</strong>-term1 na l-type termin<strong>al</strong>-name<br />

Res<strong>et</strong>s the tennin<strong>al</strong> characteristics from the tenncap entry found for termin<strong>al</strong>-name. See<br />

(not-y<strong>et</strong>-written) .<br />

s1:d<strong>et</strong>erm1ne-and-s<strong>et</strong>-termin<strong>al</strong>-type<br />

This is the routine c<strong>al</strong>led on stanup which either defaults or asks for your tennin<strong>al</strong> type.<br />

: 1 n 1 t-wi th-termcap tenncap-struct<br />

temlcap-slruC[ is what would be r<strong>et</strong>urned by si:make-termcap.<br />

19.9.2 Making More Termin<strong>al</strong> Streams<br />

As noted elsewhere (page 180), open is what may be used to open tennin<strong>al</strong> streams in <strong>NIL</strong>.<br />

The :type keyword specifics that a tennin<strong>al</strong> stream is requested:<br />

:display-tty<br />

This produces a tcnnin<strong>al</strong> stream just like that <strong>NIL</strong> starts up with. Addition<strong>al</strong> options fed to<br />

open may be used to param<strong>et</strong>erize it; these are described below.<br />

:cold-Ioad<br />

This produces a "raw" tty which has no display capahility. It docs perfonn some asciiification<br />

of non-display characters output. but perfonns no functions like line wraparound.<br />

:tty<br />

what docs this do? is it left-over from som<strong>et</strong>hing?<br />

MC:NII.MAN:NEWIO 27<br />

23-DEC-83


Termin<strong>al</strong> 110 212 Nil. Manmll<br />

Interesting addition<strong>al</strong> open keyword arguments which may be specified when opening a<br />

:dispfay-tty:<br />

:termin<strong>al</strong>-type tennin<strong>al</strong>-t),pe-name<br />

The termin<strong>al</strong> capabilities description is obtained from the tenncap entry for ;ennina!-Iypename.<br />

Since one of these is necessary. you might as weB specify the right one rather<br />

than l<strong>et</strong>ting it default (the lookup in the daLlbasc may still be necessary).<br />

:cold-load - stream colcJ.load-strt'am<br />

The first arg to open is ignored. and the innards of cold-load·stream (which must be a tty<br />

stream as created by the :cold-Ioad open-type) is extracted to g<strong>et</strong> to the re<strong>al</strong> termin<strong>al</strong>.<br />

mt.her than opening a new one. (In the ~Il )oadup process. first the termin<strong>al</strong> streams are<br />

s<strong>et</strong> to be a cold-load stream. and then later they arc res<strong>et</strong> to he re<strong>al</strong> display-tty streams<br />

using this. This is less important now than it used to he. but still COIneS in handy on<br />

occasion. It's not clear what lise it might be to users.)<br />

19.9.3 Display TTY 1\1essages<br />

In case you want to hack graphics on another termin<strong>al</strong> Uf som<strong>et</strong>hing... See <strong>al</strong>so the source<br />

code in nil $ dis k : [ nil . i 0 ] cur so r . 1 s p.<br />

: wr1 te-char char<br />

This is what implements write-char to a display tennina!. with <strong>al</strong>l the interpr<strong>et</strong>ation of<br />

char described earlier.<br />

: oustr slril1g slar! count<br />

Note start and COUIlI are not· option<strong>al</strong>. Using this results in a significant efficiency gain<br />

over individu<strong>al</strong> :write-char messages. because the stream attempts to pass <strong>al</strong>ong as many<br />

block-mode operations as possible to VMS.<br />

:wr1 te- raw~char char<br />

This is not actu<strong>al</strong>ly provided by si:dispiay-cursorpos-mixin. but is required to be<br />

supported by flavors which mix that in. It is how s;:display-cursorpos-mixin expects to<br />

g<strong>et</strong> raw codes out to the tennin<strong>al</strong>. Obviously. then. if you <strong>al</strong>so wish to g<strong>et</strong> raw ·codcs to<br />

the tenninaI, you may use this message on display tty streams.<br />

: raw-oustr SIring start count<br />

An<strong>al</strong>ogous.<br />

MC:NlI.MAN;NEWIO 27<br />

23-DEC-8J


NIl. Manu<strong>al</strong> 213 Syntax<br />

20. Syntax<br />

20.1 What the Reader Tolerates<br />

I wil1 defer delli1ed discussion of reader input and printed representation to the forthcoming<br />

("0\1\10:\ I.ISP manu<strong>al</strong> [1]. The LISP MACIlI~F LISP manu<strong>al</strong> [12] <strong>al</strong>so contains a good discussion<br />

of this. What will be presented here is basic<strong>al</strong>ly a summary of what the current ~IL reader<br />

accepts. lItilizing ("0\1\10~ !.lSI> syntax.<br />

Basic<strong>al</strong>ly. the IISP reader reads characters from a stream and fonns tokens out of them.<br />

Cert~lin characters cause addition<strong>al</strong> actions to take place: fl)r instance. the ( character \\ iII c<strong>al</strong>ise<br />

mulliple (hut possibly zero) exprcssions up to a matching ) to be formed into a list. Some<br />

characters are significant only when they are the first non-whitespace character: the # dispatch<br />

macro character behaves like this: # 0403 is the integer 259 (# 0 meaning "read in oct<strong>al</strong>"). but<br />

foo#o403 is the symbol whose name is the string "FOOH0403". Aside from these, the basic<br />

nile is that if a number can be formed from the characters of the token. it is: otherwise. it is a<br />

symbol. The sole exception is that the period character (.) is wken as a COilS £101. If a character<br />

i~ preceded h) a hackslash (\), then <strong>al</strong>l spcci<strong>al</strong> sig.nificance is rcmo\cd from it. induding ca~e<br />

translation. and it is treated as a token constituent.<br />

Thus:<br />

foobar<br />

foo\bar<br />

259.259<br />

259\.259<br />

IFooBarl<br />

IFoo\IBar\\1<br />

Similarly, the symbol whose print name is Foo 1 Bar\.<br />

259<br />

259.<br />

-259<br />

+259<br />

25\9<br />

\259<br />

1259 1<br />

the atomic symbol FOOBAR<br />

The atomic symbol whose print name is FOObAR<br />

A floating point number. (Currently this is a double-float. But see the later<br />

discussion on floating-point syntax. section 2.1.2, page 4.)<br />

The atomic symbol with print name 259.259.<br />

Vertic<strong>al</strong> bars read a symbol with an characters (except for vertic<strong>al</strong> bar and<br />

backslash) interpr<strong>et</strong>ed as constituent characters. So, this is the symbol whose<br />

print name is FooBar. Backslash may be used to include vertic<strong>al</strong> bars and<br />

backslashes in the symbol.<br />

The decim<strong>al</strong> integer 259.<br />

The decima1 integer 259. A trailing decim<strong>al</strong> point explicitly forces decim<strong>al</strong><br />

notation, not floating-point.<br />

The negative decim<strong>al</strong> integer - 259.<br />

The decim<strong>al</strong> integer 259.<br />

The symbol 259.<br />

The symbol 259.<br />

The symbol 259.<br />

MC:NII.MAN:SYNTAX 34<br />

23-DFC-83


What the Reader Tolerates . 214 <strong>NIL</strong> Manu<strong>al</strong><br />

1.0d-5 One times ten to the minus fifth power, as a double-float. Sec section 2.1.2.<br />

page 4.<br />

:foo<br />

A colon in a token uses the characters on the left to name the package the<br />

following symbol is to be read into. The "nu1l't package name means the<br />

package into which keywords are read.<br />

s;:foo The symbol FOO. read into the package named S I (the system-intern<strong>al</strong>s<br />

package),<br />

si:IFoo\IBar\\1<br />

The symhol Foc ISar\. read into the SI package.<br />

foo#0403<br />

The symbol FOON0403.<br />

I f the token consists entirely of . chamcters (and none h,I\'e been slashified). then it is illeg<strong>al</strong><br />

unless there is exactly one: that is a COIlS dOl. which is only leg<strong>al</strong> in list/cons fonnation. 'Ibus .<br />

.100. is the symbol whose print name is . FOC •• but ... is an error.<br />

The primitive syntax for a cons is<br />

«('ar . cJr)<br />

In this notation. a list of items a. b. and c would be written as<br />

(a . (b • (c . nil)})<br />

/.isl sYlllax <strong>al</strong>lows us to "elide" a cons dot with a following cons; the dot is eliminated. as are -<br />

the parentheses of the fol1owing cons:<br />

{n h . (r. . nil)<br />

(a be . nil)<br />

and fin<strong>al</strong>ly. because nil is the same as 0,<br />

(a b c)<br />

llle following characters tcnninate token formation.<br />

cncountered:<br />

( Starts a list or cons. as described above.<br />

and do som<strong>et</strong>hing speci<strong>al</strong> when<br />

) Terminates a list or cons, or some other construct which "matches" with parentheses. such<br />

as #(.<br />

"<br />

Vertic<strong>al</strong> bar terminates token formation.<br />

String syntax. The characters up to the matchine It form the string; .. and \ may be<br />

included by prcceding them with \.<br />

Reads the following expression, and "wraps" it with the function quote. Thus. 'foo· reads<br />

as (quote foo).<br />

ttBackquotc". This is used for constructing expressions. Backquote is described later<br />

(section 20.1.1, page 216). and <strong>al</strong>so in . [3].<br />

Comma is used for performing substitution within backquoted expressions (q.v.).<br />

lbe # character is a diJpauh macro characler. It reads (option<strong>al</strong>) digits as a numeric decim<strong>al</strong><br />

argument, and then dispatches off of the following character. The following arc defined:<br />

MC:NII.MAN:SYNTAX 34<br />

23-Dr:C-S3


JIm 770ns ·rss.rm<br />

<strong>NIL</strong> Manu<strong>al</strong> 215 What the Re .. ,ucr Tolerates<br />

# I expression<br />

Wraps expression with function. similar to '. Thus. # 'car reads as (function car).<br />

#(xl x2 ... xn)<br />

Reads as a simple gener<strong>al</strong> vector 11 elements long (11 may be zero). with those clements.<br />

# * bits<br />

Reads in as a simple bit vector whose elements arc bits (the digits 0 or 1). Thus. #.100<br />

is a simple-bit-vector of length 3: its clement 0 is 1, and its clements numbered 1 and 2<br />

arc both o.<br />

# Bmliol1<strong>al</strong><br />

Reads ration<strong>al</strong>. the syntax for a ration<strong>al</strong> number (which. remember. 111


What the Reader Tolerates 216 <strong>NIL</strong> Manu<strong>al</strong><br />

# ,expressioll<br />

I.oad-time ev<strong>al</strong>uation. If the expression is being reild nonn<strong>al</strong>Iy into r-.;IL, this behaves like<br />

# " However. if it is in a file being compiled. the compiler will arrange to have<br />

expression ev<strong>al</strong>uated at load (Le., vasload) time. when the containing expression is being<br />

constructed. This does not work y<strong>et</strong> in <strong>NIL</strong>.<br />

20.1.1 Backquote<br />

The bockquo/c t:1cility is used filr constructing list structure from a template. Typic<strong>al</strong>ly. most<br />

of the temp)ate is constant. and the most common use is when what is being cre~ltcd is I.lSf> code.<br />

insid~ of macro ddinilioll!\. In the simplest casco the backquote character (') is used instead of<br />

qllote ('). and. where suhstitution inside the template is desired. a fbnn to be ev<strong>al</strong>uated is<br />

preceded hy a comma character. For instance.<br />

(defmacro push (item place)<br />

t(s<strong>et</strong>f ,place (cons ,item ,place»)<br />

This definition reads in as code which is function<strong>al</strong>ly equiv<strong>al</strong>cnt to<br />

(defmacro push (item place)<br />

(list 's<strong>et</strong>f place (list 'cons item place)})<br />

Simple suhstilUlion is r. 'len llot cnough. If the commil in a backquotcd expression is immediatcly<br />

followed by an atsigr: charactcr (@), then. instead of simple substitution. the item being<br />

substituted is "spliced" into the containing list:<br />

'(foo .@bar mumble)<br />

(cons ~foo (append bar '(mumble)'»<br />

For instance. the macro<br />

(defmacro <strong>al</strong>ways-r<strong>et</strong>urning-nil (&body body)<br />

'(progn ~@body nil»<br />

produces expansions<br />

(<strong>al</strong>ways-r<strong>et</strong>urning-nil)<br />

==> (progn nil)<br />

(<strong>al</strong>ways-r<strong>et</strong>urning-nil (do-this»<br />

==> (progn (do-this) nil)<br />

(<strong>al</strong>ways-r<strong>et</strong>urning-nil (do-this) (do-that»<br />

==> (progn (do-this) (do-that) nil)<br />

The splicing is non-destructive on the expression being substituted, as if the splicing happens by<br />

use of append.<br />

In <strong>NIL</strong> (but not COMMON USP), a comma immediately followed by a dot instead of an atsign<br />

is treated similarly, except that <strong>NIL</strong> is free to use dcslructive operations for the splicing; that is.<br />

the splicing IS perfonned as if by ncone (page 58) rather than append.<br />

Backquoted expressions may be nested. They should be assumed to be expanded from the<br />

inside out. Consider the following macro definition:<br />

(defmacro defhack (name fn &aux (place-var (gentemp))}<br />

'(defmacro ,name (,place-var)<br />

'(s<strong>et</strong>f .,place-var (,',fn "place-var»»<br />

In this example. the expansion of the outer backquotc expression causes the v<strong>al</strong>ues of name, tn.<br />

andplace-var to be substituted in; this essenti<strong>al</strong>ly means that we g<strong>et</strong> (using it<strong>al</strong>ics now to show<br />

MC:NJI.MAN:SYNTAX 34<br />

23-DEC-83


.",7- 33 PC - 'sr' ;; 'm' um<br />

<strong>NIL</strong> Manu<strong>al</strong> 217 The l.isp Reader<br />

the suhstitutions)<br />

(defmacro Il<strong>al</strong>lle (place-var)<br />

t (s<strong>et</strong> f ,place-var ( • 'fn ,place-var))<br />

Now. ",111" means that we substitute in the v<strong>al</strong>ue of '''In''. which is of course just /n. which is<br />

what we want: on the other hand, we do want the v<strong>al</strong>ue of place-var to be substituted in here.<br />

so it does not need that quote.<br />

To see another way that this works. one can manu<strong>al</strong>ly pseudo-expand 111e illner backquote in<br />

the origin<strong>al</strong> defhack definition<br />

(defmacro defhack (name fn &aux (place-var (gentemp»)<br />

'(defmacro .name (.place-var)<br />

(list 's<strong>et</strong>f place-var (list' .fn place-var»»<br />

which indeed produces what we want. Gener<strong>al</strong>ly. then. one uses ".." when one wants the<br />

substituted fonn to itself he ev<strong>al</strong>uated and suhstituted with the expansion of the inner hackquote<br />

expression. and ":." when one wants to suhstitute in som<strong>et</strong>hing which is "constant" with respect<br />

to the inner backquote eXf,:msion.<br />

As one fin<strong>al</strong> extension to hackquote. ;\11 <strong>al</strong>lows its use with gener<strong>al</strong> vector syntax. This will<br />

prohably he supported fore\'\,~r and evcr. if for no other reason than the 'II compilcr/codegener<strong>al</strong>or<br />

emits inslructions as \ectors and conslructs them that way.<br />

'H(foo ,(+ 3 7) bar) => H(foo 10 bar)<br />

"Splicing" syntax (".


The Lisp Reader 218<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

;;-.-Mode:Lisp;Readtable:Ml-.-<br />

;; This code uses »:" and "I" as in maclisp.<br />

;;-.-Mode:lisp;Readtable:LM-.-<br />

:; This code reads using the old lispmachine syntax.<br />

C -.-Mode:Fortran;Readtable:Fortran-.-<br />

C This would work if one defined a readtable for Fortran.<br />

% -.-Mode:Lisp:Readtable:Cgol-.-<br />

This is lisp cod<strong>et</strong>n cgol syntax. Yow! % .<br />

define fib(x); if x


Nil. Manu<strong>al</strong> 219 The l.isp Reader<br />

s1 :enter-readtab1e "omr a-readlab/r<br />

Enters a-rrad/ablr giving the syntax for "<strong>al</strong>lle.<br />

specification in the mode-line of a source-file.<br />

name may then appear as a readtablc<br />

create-readtable<br />

R<strong>et</strong>urns a naked read table. with syntax for reading whitepace-deJimited symbols.<br />

s1:add-number-syntax<br />

Adds syntax for parsing numbers to th~ current readtable.<br />

s 1 : add -11 s t - syn tax &option<strong>al</strong> (opell # \() (closr # \)<br />

Adds syntax ftH' parsing lists to the current readwble.<br />

s1: add-pacKage-syntax &option<strong>al</strong> (eltar #\:)<br />

Adds syntax for specifing packages to the current readtable.<br />

s1:add-escape-char-syntax char<br />

tv-takes clUJr the syntax-esc,lpe-character in the current readtable.<br />

s1: add-pref1x-op-macro cliar operaTor<br />

Makes char a read macro that r<strong>et</strong>urns a list of operator and the next thing read.<br />

example.<br />

(si:add-prefix-op-macro NI' 'quote)<br />

For<br />

20.2.4 Alternative Syntax<br />

The eGOL syntax [11] is available by loading the file <strong>NIL</strong>$OISK: [<strong>NIL</strong>. LISPIO]CGOL. LOO.<br />

Further documentation is in the file <strong>NIL</strong>$OISK: [<strong>NIL</strong> .MANUAL]CGOL. TXT. The imp1cmcntors<br />

do not recommend the extensive use of CGOL or any ALGOL-Jike syntax for LISP programming,<br />

especi<strong>al</strong>ly in environments where program readability and editability arc important long range<br />

considerations. However, some feel that syntactic vari<strong>et</strong>y taken in moderation is good for the<br />

soul.<br />

egolread<br />

Rcads a CGOL syntax expression.<br />

ego 1 P r i n t expression<br />

Prints an s-expression lisp program in the CGOL syntax.<br />

Another parscr. for a language with syntax compatible with the symbolic <strong>al</strong>gcbra system<br />

MACSYMA [8], is availablc by loading the file <strong>NIL</strong>$OISK:[<strong>NIL</strong>.VAS]PARSER. which scts up a<br />

readtable named infix. The readmacro character" #$" has been s<strong>et</strong> up to invoke this parser in<br />

the "<strong>NIL</strong>" readtablc. One could then writc the following:<br />

(defun f (v a b x)<br />

#$(v[O.O]:COS«A-S).X)/(Z-Z.(A-S)AZ)+COS(V[l.l].X).<br />

v[O.l]:COS«(A+S).X)/(Z-Z*(A+S)ftZ)-V[l.G].V[O.O].<br />

v[l.O]:V[l.l].V[O,O],<br />

v[l,l]:V[O,l]*V[l.O])$)<br />

MC:NII.MAN:SYNTAX 34<br />

23-DEC-83<br />

"".. ~ .<br />

'.' . . '.' ~". .':. ': , . ' •. ~ .. ' c .~~~;. ~ \'; ,;p~j~fi;;~~':\~' ~:;=~. . •... ..... . · . .., .


Ddwgging and M<strong>et</strong>ering<br />

21. Debugging and M<strong>et</strong>ering<br />

220<br />

<strong>NIL</strong> Manu,!1<br />

21.1 Flow of Control<br />

21.1.1 Tracing<br />

tr ace junction<br />

trace enwraps the definition of junction so that the arguments it is c<strong>al</strong>led with. and the<br />

\'<strong>al</strong>ues it r<strong>et</strong>urns. may be seen. follc/iol/ is not e\'<strong>al</strong>uated.<br />

(dafun f (x) (times x x»<br />

=> f<br />

(trace f) => (F)<br />

(untrace f) => (f)<br />

(trace f) => (f)<br />

(f 3) :printout:<br />

#(1 :ENTER F #(3»<br />

#(1 :EXIT F #(9»<br />

The printout is a VECrOR. Its clements are:<br />

{O] Recursion level for the given function<br />

{I] :enter or :exit<br />

[2] Name of the function.<br />

[3J The vector of arguments, or the vector of r<strong>et</strong>urn v<strong>al</strong>ues.<br />

Say that you wanted a breakpoint on entry to f. Then say<br />

(defun f-bp (level direction name vector)<br />

(eq direction t:enter»<br />

(trace (f (:break f-bp»)<br />

Presently <strong>al</strong>l trace options work this simple and function<strong>al</strong> way, the syntax of a trace option is<br />

(:keyword predicate-junction-to-c<strong>al</strong>l). or simply :keyword which means the same thing as<br />

(:keyword t). Options are :noprint, :break, and :info.<br />

One exception: (trace (f :menue» enters a simple menue of various kinds of trace options.<br />

MC:NlI.MAN;DFBUG 20<br />

23-nEC-83


<strong>NIL</strong> ~1anu<strong>al</strong> 221 Flow of Contfol<br />

21.1.2 Who docs \Vhat, and Where<br />

who-c<strong>al</strong>ls symbol &option<strong>al</strong> &key (type:/ullction)<br />

This searches <strong>al</strong>l compiled-code modules tp find those which reference the t>pe v<strong>al</strong>ue-cell<br />

of symbol. type may take on the v<strong>al</strong>ues :functlon, :v<strong>al</strong>ue, :Ioc<strong>al</strong>-function. Of :Ioc<strong>al</strong>v<strong>al</strong>ue.<br />

It defaults to :function, thus finding <strong>al</strong>l modules which caB the function symbol.<br />

A type of :v<strong>al</strong>ue would find, <strong>al</strong>l those modules which referenced symbol as a speci<strong>al</strong><br />

variable. :Ioc<strong>al</strong>-function and :Ioc<strong>al</strong>-v<strong>al</strong>ue (which should probably be c<strong>al</strong>led :Iexic<strong>al</strong>anyway)<br />

aren't actu<strong>al</strong>ly useful: they would only find uses where the references were not<br />

compiled away, and <strong>al</strong>l loc<strong>al</strong> references are in the current compiler.<br />

Someday this should he smart enough to do searching through <strong>al</strong>l defined functions,<br />

including interpr<strong>et</strong>ed ones.<br />

where1 s function<br />

funcTion should be a symbol or a compiled-function. whereis r<strong>et</strong>urns the compiled-code<br />

module (the module-object) which d~fines fUlIctiol1. or nil if that cannot he dctennined.<br />

It can only d<strong>et</strong>ennine this for compi1ed functions.<br />

Someday (i keep saying that don't i) there will be a more gener<strong>al</strong> mechanism, so that the<br />

source file can be d<strong>et</strong>ennined for <strong>al</strong>l "defined objects", such as those defined with defvar.<br />

defstruct. defmacro. <strong>et</strong>c. Until then, note the following function:<br />

51 :module-50urce-f11e module<br />

This r<strong>et</strong>urns the name of the source file for the module module. The current<br />

implementation .does this by looking at the vasl file from which module was loaded, so<br />

that file must exist on disk (with the same name).<br />

ap rop05 STring &option<strong>al</strong> (pkg package)<br />

This searches through pkg and <strong>al</strong>l of its super-packages (see chapter 15, page 121), and<br />

r<strong>et</strong>urns a list of <strong>al</strong>l of the symbols which contain strillg as a substring.<br />

51: apropos-generate /n arg &option<strong>al</strong> (pkgpackage) (superiors I)<br />

'Ibis function maps the function fn over aU symbols which contain arg (a string or<br />

symbol) as a substring, in the package pkg (and its superiors, if superiors is not nil).<br />

si:apropos-generate uses mapatoms (page 122): it is possible that fn could be c<strong>al</strong>led on<br />

the same symbol more than once, <strong>al</strong>though that will not happen very often in the current<br />

<strong>NIL</strong> implementation.<br />

The apropos function is defined using this, by<br />

(defvar *apropos-list*)<br />

(defun apropos (arg &option<strong>al</strong> (pkg package) (superiors t)}<br />

(l<strong>et</strong> ({*apropos-list* C»~)<br />

(si:apropos-generate<br />

#'(lambda (x) (push x *apropos-list*»<br />

arg pkg superiors}<br />

*apropos-list.)}<br />

One could write \'ariants of this which test the symbol for specific properties. or with<br />

boundp or fboundp, and which print the results as they are computed rather than<br />

MC:<strong>NIL</strong>MAN:DEBUG 20


Examining Objects 222 <strong>NIL</strong> Manu<strong>al</strong><br />

accumulating them in a Jist<br />

21.2 Examining Objects<br />

exhibit object<br />

Invokes an interactive structure editor on the object. There is a "7" command to print out<br />

a command menu. The object is scnt any of the following messages. :exhibit-self.<br />

:select-nth. :store-nth. See the defi~jtions K)r built·in objects in<br />

"(N 1I .. SRC]EXH IRI.LSP".<br />

descr 1 be objcct<br />

Says a few things about the object.<br />

21.3 Debug ~lnd Breakpoints<br />

debug<br />

Enters the dehugger. Various commands. self documenting \'ia the "'!" command. Errors<br />

hy defillilt enter the debugger <strong>al</strong>so. Note that in its current SUlte, siAlck and argument<br />

infonnation displayed requires an addition<strong>al</strong> level of interpr<strong>et</strong>ation placed upon it for it to<br />

be correct. For example, loc<strong>al</strong> variable information currently shows simply the siAlek<br />

b<strong>et</strong>ween c<strong>al</strong>l frames. including argument frames being computed and "dirty" (non-Lisp)<br />

data.<br />

break. tag &option<strong>al</strong> (predicate-fi,nn I)<br />

break ev<strong>al</strong>uates predicate-!onll, which defaults to t If the result of this ev<strong>al</strong>uation is not<br />

nil. then it enters a "break loop". ":bkpt lag" is printed out. and a recursive read-ev<strong>al</strong>print<br />

loop is entered. The prompt for reading says ll)break>. where 11 is the number of<br />

nested break loops currently in force. Note that tag is not ev<strong>al</strong>uated.<br />

break is one of the older debugging tools around. It is not nearly as useful as it had<br />

once been, because in a usp with lexic<strong>al</strong>ly seoped variables, those v<strong>al</strong>ues are not apparent<br />

from the break loop. In <strong>NIL</strong> what is probably moreusefu1 would be to insert explicit<br />

c<strong>al</strong>ls to (debug) in ones code, rather than to break. )n the future. break win in fact do<br />

that. and its arguments will be a format-string and arguments for the fonnat-string (see<br />

format, page 187).<br />

-break v<strong>al</strong>ue lag<br />

This is the intern<strong>al</strong> version of break which eva)uatesboth of its arguments nonn<strong>al</strong>ly. This<br />

is <strong>al</strong>so how you can give a non-constant tag argument to the break loop. When break is<br />

changed.. this function will go away.<br />

MC:NII.MAN:DEBUG 20<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 223 M<strong>et</strong>ering<br />

21.4 1\tl<strong>et</strong>ering<br />

21.4.1 Timing<br />

t 1mer jUnction &option<strong>al</strong> (loops I) arguments<br />

C<strong>al</strong>ls jUnction with arguments arguments (a list or simple gener<strong>al</strong> vector). loops times. and<br />

print" out infonnation on how much time was taken. Try. for example.<br />

(timer #'cons 100 #(a b»<br />

Needs some improvement (() de<strong>al</strong> with function·c<strong>al</strong>1ing and loop overhead: for that reason.<br />

this is not too lI~eful with short fast functions.<br />

CO\1\10,\-IISP defines two functions for obtaining compute and elapsed time. Both r<strong>et</strong>urn<br />

integers in the same units. which can not be assumed to be fixnums. These units arc units of<br />

intern<strong>al</strong> limC'. which cannot be depended on to be the same in different CO\1\10' I.lSP<br />

implementations. They may e\"en differ from one ~IL. release to another.<br />

1 n te rn a 1-t 1 me - un 1 ts - per - second COllS1Lll1t<br />

This is .111 integer v. hich is the numher of "tic~" of intern<strong>al</strong> lime per sl'cond. It h;lprens<br />

that in 'II this is 100. because that is <strong>al</strong>l the accuracy which \\tS pn)\'ides at the<br />

moment. It could change in the future, and its v<strong>al</strong>ue should not be depended on.<br />

g<strong>et</strong>-1ntern<strong>al</strong>-run-time<br />

This r<strong>et</strong>urns the "run time" of the Nil. process in intern<strong>al</strong>-time-units-per-second units.<br />

g<strong>et</strong>-1ntern<strong>al</strong>-re<strong>al</strong>-t1me<br />

This r<strong>et</strong>urns a measure of elapsed time in intern<strong>al</strong>-time-units-per-second units. The<br />

time-base for this time measurement may not be depcnded on: only differences b<strong>et</strong>ween<br />

the v<strong>al</strong>ues of two successive c<strong>al</strong>ls should be used for anything.<br />

runtime<br />

This is the old name for g<strong>et</strong>-intern<strong>al</strong>-run-time. While it is the- same name as the<br />

MACLISP function, it is incompatible-the <strong>NIL</strong> runtime function r<strong>et</strong>urns the run time in<br />

units of hundredths of a second.<br />

elapsed-time<br />

time<br />

elapsed-time r<strong>et</strong>urns a measurement of elapsed time. in seconds. as a double·fioat. Two<br />

such quantities may be compared to d<strong>et</strong>ermine elapsed time. The origin of this number<br />

may not be depended upon: in MACLISP it is the "system uptime"; in ~lL it happens to<br />

be the double·float representation of the number of seconds since thc origin of the<br />

Smithsonian time standard (loc<strong>al</strong> time). This quantity is only re<strong>al</strong>ly accurate to hundredths<br />

of a second. even though it is potenti<strong>al</strong>ly accurate to IOO-nanosecond tics.<br />

The synonym time is provided for MACTISP compatibility; This name should not be used<br />

in new programs. and should be changed in old programs. as the name time will be<br />

ch~l11ged incomp~ltihly by CO\1:\10~ I.Isr. Also. there is a us» \1ACIII'F I.ISP time<br />

function which r<strong>et</strong>urns elapsed time. but as a fixl1um in sixti<strong>et</strong>hs of a second. The<br />

elapsed-time function will continue to exist as the function<strong>al</strong> equi\<strong>al</strong>cnt to the MACLISP<br />

MC:NII.MAN:DEBUG 20<br />

23-1 )FC·g3<br />

i<br />

.'. ;-,'<br />

~<br />

~<br />

.. ~<br />

,_:::;,:~~::~~~~:~'o~~',~__ ~:~~: ~: , _- _. . .


Melering 224 Nil. MmlU,d<br />

time function. however.<br />

s1:pagefault-count<br />

This r<strong>et</strong>urns the number of pagefaults taken by the process since process creation.<br />

Although this number is interesting to look at to see if the !\:IL is thrashing. it must be<br />

taken with sever<strong>al</strong> grains of s<strong>al</strong>t due to the way VMS paging/swapping is perfonned. {The<br />

following discussion should perhaps be somewhere else. under "perfonll<strong>al</strong>lce considerations"?)<br />

The following points arc especi<strong>al</strong>ly of notc. First this number docs not count the<br />

number of faults taken which involved fctchjng a page from the pagefile (or shared image<br />

file). Rather. it includes those "fault\" for pages which still reside in physic<strong>al</strong> memory,<br />

hut are just not contained within the working s<strong>et</strong> Also. the overhead of doing this<br />

paging is charged to thc process nmtime.<br />

Presumably. then. if one s<strong>et</strong>s the working-s<strong>et</strong> extent (the proccss param<strong>et</strong>er/user quota<br />

WSEXTENT) high, then the actu<strong>al</strong> working s<strong>et</strong> in use will apprmlch the number of pagcs<br />

of the joh which arc resident in physic<strong>al</strong> n:tcmory. and the count of pagcfaults will b<strong>et</strong>tcr<br />

approximate the number of pagefautts for non-resident pages.<br />

Note <strong>al</strong>so the room function. whichvcrboscJy describes the "irtu<strong>al</strong> memory usage of the !\IL.<br />

including the size of the living heap (Le .. how much consing has been going on).<br />

The ~1A(,usP·compatible status macro provides a gctime option which r<strong>et</strong>urns the nmtimc (in<br />

the same unite; as runtime docs) which is the contribution to the proces~ runtime hy the garhagccollector.<br />

This is curr~ntly. of course. <strong>al</strong>w~lYs zero, When the garhage-c~1ncctor is availahle, there<br />

will be functions which par<strong>al</strong>lel the above threc. which will r<strong>et</strong>urn the contributions to elapsedtime.<br />

runtime. and pagefaults by the garbage-collector. Note that the v<strong>al</strong>ues r<strong>et</strong>urned by the<br />

above functions will· <strong>al</strong>ways include the contributions by the garbage-collector .<br />

. 21.4.2 Function C<strong>al</strong>ling<br />

The only type of function c<strong>al</strong>l m<strong>et</strong>ering which is available in <strong>NIL</strong> right now is a glob<strong>al</strong><br />

database of how many function c<strong>al</strong>ls (and similar things) of various types have been perfonned<br />

since the <strong>NIL</strong> was first loaded up.<br />

This number-of-function-c<strong>al</strong>ls m<strong>et</strong>ering is basic<strong>al</strong>ly. implemented by the <strong>NIL</strong> compiler. There<br />

are four tables 10 long: the four tables are for m<strong>et</strong>ering<br />

jUnction C'a/ls<br />

Direct function c<strong>al</strong>ls. As in (defun f (x) (g x»).<br />

jUnc<strong>al</strong>/s<br />

Simple func<strong>al</strong>ls.<br />

sends<br />

C<strong>al</strong>ls to send. 'Ibis does not (unfortunately) include lexpr-send.<br />

applies<br />

Cumpiled c<strong>al</strong>ls to apply (= lexpr-funcaU).<br />

lbe 10 entries in c,tch table count the number of such occurences for zero through eight. and<br />

nine-or-more arguments. When the compiler compiles (say) a function caU of two arguments, it<br />

MC:NII.MAN:I1EBUG 20<br />

23-DFC;'S3


<strong>NIL</strong> Manu<strong>al</strong> 225 M<strong>et</strong>cring<br />

will sneak in an instnJction like<br />

incl w A<br />

cl$c<strong>al</strong>l_m<strong>et</strong>er+2(slp)<br />

just before it does the actu<strong>al</strong> function c<strong>al</strong>l. This sequence takes four bytes of code.<br />

The intent of this type of m<strong>et</strong>ering is to measure how intensively various applications perfonn<br />

function c<strong>al</strong>ling. in order that we might· be able to estimate how changes to the function c<strong>al</strong>ling<br />

sequence (such as modifications to the function entry code. function c<strong>al</strong>l-frame s<strong>et</strong>up code. or<br />

even microcode support for either of those or the function can itself) might affect the performance<br />

of 'II programs. Wc have not y<strong>et</strong> actu<strong>al</strong>ly done any measurements with these m<strong>et</strong>ers. However.<br />

in the event that they might be useful to' people. the functions (which are somewhat dirty and<br />

kluog.cy) which read them are documented below.<br />

s1:g<strong>et</strong>-c<strong>al</strong>1-m<strong>et</strong>ers<br />

This r<strong>et</strong>urns an a-list of the v<strong>al</strong>ues of the various c<strong>al</strong>ling m<strong>et</strong>ers. The a-list will be 4 long.<br />

and the first clement of each of these lists is a keyword describing the type of c<strong>al</strong>l: the<br />

remaining 10 clements are the numher of "c<strong>al</strong>ls" of that type for zero through 8. and<br />

(last) nine or more c<strong>al</strong>ls. The keywords are<br />

:function<br />

Direct function c<strong>al</strong>ls<br />

:func<strong>al</strong>l<br />

Compiled c<strong>al</strong>ls to funeaU<br />

:send<br />

Compiled caJIs to send<br />

:apply<br />

Compiled c<strong>al</strong>ls to apply (Iexpr-func<strong>al</strong>l).<br />

s i : show-ca l1-m<strong>et</strong>ers &option<strong>al</strong> (merers (si:ger-c<strong>al</strong>l-m<strong>et</strong>ers)<br />

Prints out the m<strong>et</strong>ers.<br />

s 1 : subtract-ca l1-m<strong>et</strong>ers after-m<strong>et</strong>ers be/ore-m<strong>et</strong>ers<br />

R<strong>et</strong>urns a new "m<strong>et</strong>ers Hst" in which <strong>al</strong>l of the numbers are the difference of the after<br />

and before v<strong>al</strong>ues. All of the entries are assumed to be in the same order.<br />

One could g<strong>et</strong> a display of how much function c<strong>al</strong>ling (<strong>et</strong>c.) was going on by doing som<strong>et</strong>hing<br />

like<br />

(l<strong>et</strong> ({before (si:g<strong>et</strong>-c<strong>al</strong>1-m<strong>et</strong>ers»)<br />

(run-program)<br />

(si:show-c<strong>al</strong>l-m<strong>et</strong>ers (si:g<strong>et</strong>-c<strong>al</strong>1-m<strong>et</strong>ers) before»<br />

MC:NII.MAN:DFBUG 20<br />

23-DFC-83


__________________'1-...<br />

r~ .... r.r.n ...... ".;.-·.·r.711'17171711'1'17711111)1IIIIIIII<br />

System Management 226 Nfl. Manu<strong>al</strong><br />

21.5 System l\1anagement<br />

Included are some minim<strong>al</strong> uti1ity functions for maint<strong>al</strong>nmg subsystems in ~1L. These tools<br />

are not meant to be a comprehensive s<strong>et</strong>. ttaddressing <strong>al</strong>l the issues" as they say. Instead. they<br />

address some of the issues. have been found' useful. and are used <strong>al</strong>ong with individu<strong>al</strong> system<br />

specific procedures for maintaining systems including the editor and MACSYMA.<br />

The practic<strong>al</strong> working procedure on most programs goes som<strong>et</strong>hing like the following: 'lbcre<br />

are a s<strong>et</strong> of source files that make up the program. One of these files defines a variable s<strong>et</strong> to a<br />

list of these file names. and includes code for loading the files. creating needed package<br />

namespace(s). and peforming other functions as needed. Day-tn-day works procedcs in an<br />

increment<strong>al</strong> t~lsion. changes are made to the sources using the {-wilt-in editor. and thcse changes<br />

arc testcd and dchugged using editor commands such as CONTROI,-META-C (compile-dcfun. or<br />

-Z) and other lIlilitcs in the system<br />

as needed. The editor. dehugger. ev<strong>al</strong>uator. andexhihitor are invoked many times during a days<br />

dcvelopment cycle. From lime to time during editing t1le changed files arc saved of course. as a<br />

h(l~kup against environment crashes. At the end of ~hc day. (or perhaps. during lunch hour. or<br />

after sever<strong>al</strong> days). a recompil<strong>al</strong>ion of the changed program files may he eflected. using some of<br />

the functions documented in this section.<br />

A somewhat par<strong>al</strong>1el effort is the maintainencc of a system t11at has "users." The same<br />

melhodology as lIsed in a development system is in effect: except tJ1at now the full-rccompilationcycle<br />

time may he months. and there is a definite targ<strong>et</strong>-environment which is (0 receive system<br />

ch~!!~g~s in t.~c ferm of "p~tch files." {Sec the d~x:umenc~tion of the put~h fucility.}<br />

Some addition<strong>al</strong> functions documented here provide ways to find out som<strong>et</strong>hing about how<br />

modules depend on one another.<br />

21.5.1 An example<br />

; This is an example "system-build" file.<br />

(defparam<strong>et</strong>er .my-files.<br />

'("USR:[ME.SYS]TOPLEVEL"<br />

"USR:[ME.SYS]UTILS"<br />

"USR:[ME.SYS]BASIC"»<br />

(defvar .my-modules. (»<br />

(defun load-my-system ()<br />

(s<strong>et</strong>q -my-modules. (mapcar "load .my-files.»)<br />

(de'fun recompi le-roy-fi les()<br />

(mapcar ,'silent-comfile<br />

(mapcan "(lambda (x)<br />

(if (utils:source-need-compile? x)<br />

(list x»)<br />

.my-files.»)<br />

MC:NII.MAN:DFHUG 20<br />

23-DEC-S3


<strong>NIL</strong> Manu<strong>al</strong> 227<br />

SySl~tn<br />

ManJgcm~nt<br />

{defun silent-comfile (x)<br />

{l<strong>et</strong> «compi1er:*messages-to-termin<strong>al</strong>? (})<br />

(si:print-gc-messages ())}<br />

(comfile x)}}<br />

(defvar *my-undefined-functions-<strong>al</strong>ist*<br />

( ) )<br />

(defun find-my-undefined-functions ()<br />

{s<strong>et</strong>q *my-undefined-functions-a1ist* ()}<br />

{mape<br />

# ' ( 1 amb d a (m)<br />

(if (typep m 'module)<br />

(uti1s:map-over-modu1e-ce11s<br />

#'(lambda (module symbol key)<br />

(if (and (eq key :fun<strong>et</strong>ion)<br />

(not (fboundp symbol»)<br />

(l<strong>et</strong> «a (assq<br />

symbol<br />

*my-undefined-functions-a1ist*»)<br />

{i f a<br />

(unless (memq module (cdr a»<br />

(push module (cdr a»)<br />

(push<br />

(list symbol module)<br />

*my-undefined-functions-<strong>al</strong>ist*»»)<br />

m) ) )<br />

*my-modules*)<br />

*my-undefined-functions-<strong>al</strong>ist*)<br />

21.5.2 "Source (Re)Compilatioo"<br />

ut11s:V8s-source-f11e filename<br />

G<strong>et</strong>s the exact name of source file from the object file, filename.<br />

ut 11 s: source-need-comp 11 e1 source-filename &option<strong>al</strong> object-directory<br />

If there is no object file. or if the version of the number of the present source file is<br />

greater than the version number of the source from which the object was compiled then<br />

this function r<strong>et</strong>urns t.<br />

ut 11 s: V8S- source-needs - recomp11 81 filename<br />

G<strong>et</strong>s the source file name for the object filename and checks the version numbers.<br />

MC:NII.MAN:DEBUG 20


Verifk~ltion 228 <strong>NIL</strong> Manu<strong>al</strong><br />

21.5.,3 Information in l\1odules<br />

The exhibit function can be used to look at modules interactively.<br />

21.5.4 Related Utilities<br />

These are som<strong>et</strong>imes used to store information gathered during system programming. for<br />

example. "bug" cases. lists of undefined functions. sorted lists of speci<strong>al</strong> variables. ctc.<br />

ut i 1 s : p r i" t - i" to - f 1·1 e rXl'rcsshm &option<strong>al</strong> filellame<br />

Prints the {'.%prt'ssioll into the .li/('/I


<strong>NIL</strong> Manu<strong>al</strong> 229 Errors<br />

22. Errors<br />

Errors in <strong>NIL</strong> work by sign<strong>al</strong>ling error conditions using sign<strong>al</strong>. The specifics of this are going<br />

to be changing in various ways: however, the basic interfaces for "creating" errors can hopefully<br />

be kept static, at least insofar as the functions can be made to accept and interpr<strong>et</strong> arguments<br />

upwards-compatibly.<br />

cerror proceedable restartable condition-name lonna/-sIring args<br />

This is what needs to be used to sign<strong>al</strong> correctable errors. For an error to be correctable<br />

(in the current scheme). one uses cerror and gives a non-null proc('cdab1c argument. The<br />

rC.'ilarlah!c arg.ument has lO do with saying that the error can be "restarted" (i.e..<br />

som<strong>et</strong>hing g<strong>et</strong>s tried over again) by throwing to a 141g with name error-restart: this is<br />

hardly. if ever. used. and will probilbly be obsol<strong>et</strong>e quite soon.<br />

condition-name is the name of the condition being sign<strong>al</strong>led: it is typic<strong>al</strong>ly. <strong>al</strong>though not<br />

necessarily. a keyword.<br />

fhrl11a1-Sfrillg is a string suitahle as an argument to format with extra arguments of args:<br />

that i~ how the error message is produced. There arc. however. COl1\ entions on what<br />

particular arguments mean for particular conditions: some of them arc described below.<br />

At some point. the error system and how errors (and non-error conditions) arc sign<strong>al</strong>led<br />

will <strong>al</strong>l change. It should be the case, however. that vanilla uses of cerror, especi<strong>al</strong>ly<br />

cheCK - type place l)'pe-~pecifie,. &option<strong>al</strong> description<br />

check -type expands into code which verifies that the v<strong>al</strong>ue of place (which must be a<br />

place suitable for use with s<strong>et</strong>f-see page 38) is of the type type-specificr. If it is not,<br />

then an error is sign<strong>al</strong>led and place is updated to the newly-supplied v<strong>al</strong>ue. Note that<br />

type-specifier is not ev<strong>al</strong>uated.<br />

description is a string which describes the type; for instance. "an integer", "a prime<br />

number greater than 403". If it is not supplied. then check-type will attempt to<br />

construct such a phrase from type-specifier; however, the current implementation barely<br />

tries at <strong>al</strong>l. so for now it is probably best to specify it.<br />

For example,<br />

(defun oddp (x)<br />

(check-type x gaussian-integer "a guassian integer")<br />

(if (typep x 'complex)<br />

(if (not (logbitp 0 (re<strong>al</strong>part x»)<br />

(logbitp 0 (imagpart x»<br />

{not (logbitp 0 (imagpart x»»<br />

(logbitp 0 x»)<br />

MC:NII.MAN:ERROR 15<br />

23-DEC-83


Errors 230 Nil. Mclllu<strong>al</strong><br />

check - arg place predicat(, &option<strong>al</strong> sIring<br />

check-arg is an oldcr form of check-type. predicate. if it is atomic. is a function of<br />

one argument to be used to test the v<strong>al</strong>ue of place:<br />

(check-arg x fixnump "a fixnum")<br />

I f it is not atomic. then it is a form to· be ev<strong>al</strong>uated to test to see if the v<strong>al</strong>ue of place is<br />

acceptable:<br />

(check-arg x (typep x '(signed-byte 8»<br />

"an eight-bit signed byte")<br />

Even if it wcre to try. check-arg would have even m()r~ tfouhlcconstructing a<br />

descriptivc string on its own than check -type. s() it is rccommended that siloing be<br />

supplicd.<br />

For example.<br />

(defun fact (x &ayx Cans 1»<br />

(check-arg x" (typep x '(integ.er 0 .»<br />

"a non-negati~e integer")<br />

(do «i 2 fl+ i») «>= ; x) ans)<br />

(s<strong>et</strong>Q an~ (* i ans}}})<br />

Hcre are somc of the interesting and well-fonned error conditions defined in <strong>NIL</strong> right now.<br />

and t11e arguments they expect. (Notc that extra arguments may <strong>al</strong>ways be given.)<br />

:wrong- type - argument type-name losing-object<br />

This has to be the most common condition uscd in <strong>NIL</strong>. type-name is the name of the<br />

type of object which was expected. such as number. and los;llg-o~i('ct is the ooject. (The<br />

type-name is not currently used fOf anything. and lots of code just puts a fairly random<br />

symbo1 there.) The v<strong>al</strong>ue r<strong>et</strong>urned is used in place of the v<strong>al</strong>ue of the wrong type. For<br />

example. a subroutine which arg-checks for fixnum:<br />

(defun si:require-fixnum (x)<br />

(do () «fixnump x) x)<br />

(s<strong>et</strong>q x (cerror t nil :wrong-type-argument<br />

"-.-5 is not a fixnum"<br />

'fixnum x»»<br />

Wrong-type-argumcnt checks are so common that it is b<strong>et</strong>ter to subroutinize or macroify<br />

them rather than writing out loops. See, for instance. check -arg (page 230).<br />

:unbound-variable variable<br />

variable was not bound. R<strong>et</strong>urning a v<strong>al</strong>ue uses that as the variable instead..<br />

:undefined- function name<br />

name is not defined as a function.<br />

instead.<br />

R<strong>et</strong>urning a v<strong>al</strong>ue uses that as the function name<br />

:wrong - number - of -arguments random<br />

This is handled spastic<strong>al</strong>ly right· now. will probably be superceded by som<strong>et</strong>hing else. At<br />

least when c<strong>al</strong>led from compiled code. r<strong>et</strong>urning a v<strong>al</strong>ue causes that v<strong>al</strong>ue to be r<strong>et</strong>urned<br />

as if from the losing c<strong>al</strong>l.<br />

:inv<strong>al</strong>id - form fonn<br />

fonn was not meaningful to ev<strong>al</strong>. The r<strong>et</strong>urn v<strong>al</strong>ue is ev<strong>al</strong>uated in place of the bad fonn.<br />

MC:<strong>NIL</strong>MAN:ERROR 15<br />

23-l>EC-S3


NIl. Manu<strong>al</strong> -231- Errors<br />

:io -Iossage t/escril'l ion Jonn<br />

Sort of a catch-<strong>al</strong>l for random I/O errors. description is a string describing the error. and<br />

Jonl1 is the form which produced it; for instance<br />

(del<strong>et</strong>e-file "[fooJbar.baz")<br />

might sign<strong>al</strong> a :io-Iossage error with a descriplion of the string<br />

"%RMS-E-DNF, directory not tound"<br />

and a Jonn like<br />

(del<strong>et</strong>e-file #


En\'ironmelll Enquiries<br />

23. Environnlent Enquiries<br />

. 232<br />

Nil. Mm1U,tJ<br />

23.1 The Host Environment<br />

lisp-implementation-type<br />

This r<strong>et</strong>urns a string which is the name of the uSP implementation, In NIl, this string is<br />

"VAX <strong>NIL</strong>".<br />

lisp-implementat1on-version<br />

This function r<strong>et</strong>urns a string which descrihes the \'ersionsof the systems loaded in the<br />

!\1I. In :\11,. this is the S4Ulle as c<strong>al</strong>ling (si:system-version -info t) (see pitge 282 for<br />

more d<strong>et</strong>ails).<br />

maChine-type<br />

This r(,lllms a string which names the type of machine the !':ll. is running on. such as<br />

"DEC VAX-11/7SO".<br />

machine-instance<br />

Relllrn~a<br />

string which is a (supposedly) unique string naming the m,tchine. such as<br />

"MIT-CORWIN". 'Jbis name wjJJ nonnaJly be the same as that used as the "host" name<br />

by the path name code.<br />

host-software-type<br />

'Ibe sofrware type of the machine. In NIl .•<br />

short-site-name<br />

this is <strong>al</strong>ways "VMS".<br />

This r<strong>et</strong>urns a shon name of the site, for instance "MIT AI Lab", If this was not s<strong>et</strong> up<br />

in the ~II site param<strong>et</strong>ers file. it win default to what is r<strong>et</strong>urned by tJle machineinstance<br />

function.<br />

long-site-name<br />

This r<strong>et</strong>urns a long name for the site. such as "MIT Artifici<strong>al</strong> Intelligence Laboratory",<br />

If this was not s<strong>et</strong> up in the <strong>NIL</strong> site param<strong>et</strong>ers file, it will default to me shon site name<br />

(above). or the machine instance.<br />

23.2 Maclisp-CompatibJe Status Enquiries<br />

(status date)<br />

r<strong>et</strong>urns a list of the year (modulo 100), month. and day of the month.<br />

(status daytime)<br />

r<strong>et</strong>urns a Jist of the current hour, minute, and second.<br />

(status dow)<br />

r<strong>et</strong>urns a symbol which is the fun name of the current day of the week (in English,<br />

sorry), lbe package the symbol is inlCrned in is probably system-intern<strong>al</strong>s: perhaps it<br />

should be the keyword package, or the v<strong>al</strong>ue should be a string anyway.<br />

MC:NII.MAN;ENV 37<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 233 Privileges<br />

(status gctime)<br />

R<strong>et</strong>urns the runtime contribution of the garbage-collector. This is. of course, <strong>al</strong>wilYs 0 in<br />

the current <strong>NIL</strong>.<br />

The first four of these may <strong>al</strong>l be obtained by use of the functions in section 23.5. page 234.<br />

23.3 Privileges<br />

g<strong>et</strong>-privileges<br />

This r<strong>et</strong>urns a list of keywords naming the privileges the ~IL<br />

keywords are listed below.<br />

currently has enabled. The<br />

s<strong>et</strong>-privileges &rest kC)'lt'ortis-and-l'o/U(,S<br />

This takes as arguments <strong>al</strong>ternating privilege keywords and flags: if the flag is nil, the<br />

corresponding privilege is disabled. otherwise it is enabled (if that is possible). s<strong>et</strong>privileges<br />

r<strong>et</strong>urns a list of the privileges which were enabled when it finished, just as<br />

g<strong>et</strong> - privileges docs. For instance.<br />

(s<strong>et</strong>-privileges :sysprv t :bypass nil)<br />

(attempts to) turn on the sysprv privilcgc, (lnd turn offthc bypass privilcge.<br />

The privilege keywords defined are<br />

:cmkrnl<br />

:cmexec<br />

:sysnam<br />

:grpnam<br />

:<strong>al</strong>lspool<br />

:d<strong>et</strong>ach<br />

:diagnose<br />

:Iog_io<br />

:group<br />

:acnt<br />

Note that for this privilege, the name used in VMS is noacnt; however, <strong>NIL</strong> uses acnt<br />

because that is the name used by DeL.<br />

:prmceb<br />

:prmmbx<br />

:pswapm<br />

:<strong>al</strong>tpri<br />

The intern<strong>al</strong> name for this is s<strong>et</strong>pri, however OCL uses <strong>al</strong>tpri, so <strong>NIL</strong> does <strong>al</strong>so.<br />

:s<strong>et</strong>prv<br />

:tmpmbx<br />

:worfd<br />

:mount<br />

:oper<br />

:exquota<br />

:n<strong>et</strong>mbx<br />

:volpro<br />

:phy_io<br />

MC:NII.MAN:ENV 37<br />

23-DEC-8J


Memory Usage<br />

234 <strong>NIL</strong> Manu<strong>al</strong><br />

:bugchk<br />

:prmgbl<br />

:sysgbl<br />

:pfnmap<br />

:shmem<br />

:sysprv<br />

:bypass<br />

:syslck<br />

2.14 l\lemory Usage<br />

room &option<strong>al</strong> str('am<br />

room prints out a fitirly verhose English description of the virtu<strong>al</strong> memory usage of the<br />

'II.. and some related infunnation. In panicular. one of the things it tells is an<br />

estimation of how much space is left for expansion of the !i"illg heap. ~hich is where aU<br />

ordinary consing is pcrfonncd.<br />

Note <strong>al</strong>so the si:pagefault-count function. pagc 224.<br />

23.5 Time and Date<br />

(See <strong>al</strong>so section 23.2. page 232.)<br />

Nil. provides a s<strong>et</strong> of functions for manipulating dates and timcs. A date and time is .<br />

represented in one of two ways: by a ullivers<strong>al</strong>-time, which is an integer number of seconds from .-<br />

00:00 January 1. 1900 GMT, and as a decoded time. which consists of the following components:<br />

seconds<br />

minutes<br />

hours<br />

date<br />

month<br />

The one-origined month number: January is 1, <strong>et</strong>c.<br />

year<br />

The full year, e.g., 1983.<br />

day-of week<br />

The zero-origined day of the week: 0 is Monday, 1 is Tuesday, and 5 is Sunday.<br />

daylighr-sQvings-time-p<br />

t or nil, depending on wh<strong>et</strong>her the decoded time is daylight savings time.<br />

timezone<br />

The number of the timclone: 0 is Greenwich time. 5 is Eastern time, -2 is Eastern<br />

European time, and -4.5 is Indian Standard time.<br />

This decoded time is not represented in any datastructure, but rather is r<strong>et</strong>urned as multiple<br />

v<strong>al</strong>ues by functions which decode univers<strong>al</strong>-time, or passed as argument'i as other functions.<br />

MC:NII.MAN:ENV 37<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 235 Time and I )ate<br />

23.5.1 The Main Functions<br />

The functions in this section arc defined by CO~MO~-I.ISP.<br />

without any package qu<strong>al</strong>ification.<br />

and <strong>al</strong>l may be referred to<br />

g<strong>et</strong>-un1vers<strong>al</strong>-t1me<br />

This r<strong>et</strong>urns the current time in univers<strong>al</strong>-time fonnat.<br />

g<strong>et</strong>-decoded-t1me<br />

This r<strong>et</strong>urns the current time. decoded. as 9 v<strong>al</strong>ues: the current second. minute. hour.<br />

date. month. year. day-or-week. daylight-sadngs-time-p. and time/one. It is <strong>et</strong>lccti\'c1y<br />

(decode-univers<strong>al</strong>-time (g<strong>et</strong>-univers<strong>al</strong>-time))<br />

decode-univers<strong>al</strong>-t1me Ullil'('rsa/-/ill/c &option<strong>al</strong> /il11c:ol1(,<br />

liIllC:UIIC dcl:IlI1t~ to the current timezone (sec page 238). This decodes IIl1ivcrstJ/-liIllC with<br />

respect to lilllc:CJ/lc. and r<strong>et</strong>urns 8 \'<strong>al</strong>ues: the second. minute. hour. d<strong>al</strong>e. month. year,<br />

day-of-week. dayliglll-sa\'ings-time-p. and time7one.<br />

encode-univers<strong>al</strong>-t1me seconds III;IIU/C.\ hours d<strong>al</strong>l' 11101l/1i yCelr &option<strong>al</strong> lil11(':o1/('<br />

tiIllC:OIIC dcf~lllltS to the current [imczone. This encodes the gin:'11 date and time for the<br />

timelone. and r<strong>et</strong>urns a univers<strong>al</strong>-time.<br />

23.5.2 Printing Dates and Times<br />

The following functions arc not glob<strong>al</strong>i7ed. but must be referred to with the time: package<br />

prefix. Most of them arc the same as those provided by LISP MACHINE LISP. All of them take a<br />

des/illatioll argument. which may be a stream. t. or nil. t means use the v<strong>al</strong>ue of standardoutput:<br />

nil me4tns r<strong>et</strong>urn the result as a string. Note that this is compatible with the way the<br />

format function (page 187) interpr<strong>et</strong>s its destination argument. not the way the regular <strong>NIL</strong><br />

printing functions do. The destination <strong>al</strong>ways defaults to t, meaning print the output on<br />

stand ard - output.<br />

time: pr1 nt-t 1me seconds minutes hours da)' month year &option<strong>al</strong> (destination t)<br />

This prints the specified date and time in brief fonnat, to destination. The fonnat used is<br />

"10/03/83 23:02:59"-the month number, the day in the month, the year (modulo 100),<br />

and the time.<br />

t1me:pr1nt-current-t1me &option<strong>al</strong> (destination I)<br />

This docs time:print-time of the current time.<br />

1<br />

t 1 me: p r 1 n t - u n 1 ve r s a 1-t 1 me ullivers<strong>al</strong>-time &option<strong>al</strong> (destination I) limezone<br />

This effectively docs decode-univers<strong>al</strong>-time on univers<strong>al</strong>· lime and timezone (which<br />

defaults to the current timezone). and then time:print-time of the results to destination.<br />

MC:NIIMAN:ENV 37<br />

23-DEC-83


...<br />

Time and Date 236 <strong>NIL</strong> Manu<strong>al</strong><br />

t 1me: pr1 nt-date srcOIu/s minutes hours date month year day-oflhe-week &option<strong>al</strong><br />

(deslillatioll/)<br />

This prints the date in a fonnat like<br />

Friday the seventh of October, 1983; 11:02:59 pm<br />

t 1me :print-current-date &option<strong>al</strong> (deslination I)<br />

Prints the current date. in time:print -date fonnat.<br />

t 1me: pri nt-un 1 versa l-date ul1il'ers<strong>al</strong>-time &optionaI (deslination I) limezolll'<br />

Uses time:print-date to print tile decoding of univers<strong>al</strong>-time and limeZ()l1e.<br />

time: pr 1 nt - br 1 ef -un 1 versa 1-t 1me ullh'rrs<strong>al</strong>-limr &oplionaJ (drs/ina/iol1/) rcferc'II('('-/imr<br />

This prints ul1irrrs<strong>al</strong>-limr in a format likc 10/07/83 23:02. Hnwc\'cr. portions of it wilJ<br />

hc omitted if they are the same· as the corresponding components of the univers<strong>al</strong>-time<br />

refrrencr-/ime (which dcfllllits to the current time). In particular. if the year is the same.<br />

it is omitted. and if the month and day are <strong>al</strong>so the same. the entire date is omitted. So<br />

depcnding on the reference time. one COUld. gel 10/07 23:02 or even just 23:02.<br />

time: p r 1 nt-un 1 versa l-ma i 1-format -date Ullirrrs<strong>al</strong>-lilllc &optionClI (dCSlilJ(1Ii011/)<br />

Prints thc date and time specified by univers<strong>al</strong>-limr in "mail fnnnat". This is a fnnnat<br />

which conforms to that specified in RFC822. "Standard for the fonnat of ARPA Intern<strong>et</strong><br />

Text Messages" [6]. It looks like<br />

Fri, 7 Oct 83 23:02:59 EDT<br />

t 1me: pr1 nt-current-ma 11-tormat-date &option<strong>al</strong> (des/inatiollt)<br />

Prints the current dilte and time. using time:print-universaf-mail-format-date.<br />

23.5.3 Namings<br />

The time package contains a sm<strong>al</strong>l database of names of months and days of the week. in<br />

various formats. The format is split <strong>al</strong>ong two dimensions: the mode. for instance :Iong,<br />

:medium, or :short, and the language. such as :english. There is a glob<strong>al</strong> default for each of<br />

these: .<br />

t1me:*default-language.<br />

The default v<strong>al</strong>ue of this is :english.<br />

time:*d<strong>et</strong>au1t-mode.<br />

The default v<strong>al</strong>ue of this is :Iong.<br />

Variable<br />

Variable<br />

The mode and language are combined (by lookup) into a composite symbol for which the<br />

lookup of the actu<strong>al</strong> text fonnat is performed. For the following functions. one may specify this<br />

composite symbol. such as :long-engJish. just the mode (:Iong), in which case the default<br />

language is used. or just the language. in which case the default nlUde is used. The three<br />

predefincd modes are :lon9. :medium. and :short. and there are entries for the languages<br />

:english. :french. :german. :spanish. and :itatian. Not <strong>al</strong>l mode/language comhinations are<br />

supported: in particular. :medium is treated as a speci<strong>al</strong> case. such that if it is not fimnd. :short<br />

is tried instead. lbc :short mode typic<strong>al</strong>ly implies the short standard abbreviation: this is usu<strong>al</strong>ly<br />

three characters. however it· is two for :german.<br />

MC:<strong>NIL</strong>MAN:ENV 37<br />

23'DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 237 'I'ime and I )ate<br />

t 1 me: mon t h - s t r in g mOlllh &option<strong>al</strong> f1lodespec<br />

R<strong>et</strong>urns a string naming thc month. in thc fonnat spccificd by mot/l'spec. Assuming the<br />

initi<strong>al</strong> dcfault v<strong>al</strong>ues for time:*default-Ianguage* and time: *default-mode*,<br />

(time:month-string 12) => "Decembertt<br />

(time:month-string 12 :short) => ttDec"<br />

(time:month-string 12 :spanish) => "diciembre"<br />

(time:month-string 9 :medium) => "Sept"<br />

(time:month-string 9 :short) => ttSep"<br />

time: day-of-the-week-string day-oJ-the-week &option<strong>al</strong> l1lodespec<br />

Similar:<br />

(time:day-of-the-week-string 1)<br />

(time:day-of-the-week-string 1 :short)<br />

(time:day-of-the-week-string 1 :medium)<br />

(time:day-of~the-week-string 1 :german)<br />

(time:day-of-the-week-string 1 :short-german)<br />

=> "Tuesday"<br />

=> "Tue"<br />

=> ItTues lt<br />

=> "Dienstag"<br />

=> ItDilt<br />

t1me:mode-language-f<strong>et</strong>ch modespec hash-Iable what<br />

This is the primiti\ e v. hich canonic<strong>al</strong>izes the modc. languagc. or composite symhol into a<br />

compositc symhol, and looks that up in hash-fable. what is just a dcscriptivc string for<br />

error rcporting. e.g.. "Month namc". The two above functions use this function to<br />

r<strong>et</strong>rievc vcctors from thc following hash tables. which arc thcn indcxcd into to gct the<br />

namcs.<br />

time: *month-str 1 ngs*<br />

Variable<br />

This is a hash tablc associating the composite mode/language symbols (e.g., :long-engHsh.<br />

:short-german) with vectors of the strings for the given months. The vcctors are zeroorigincd.<br />

so 1 must bc subtracted from the month number bcfore the aref (or sgvref) is<br />

perfonned. The vectors are <strong>al</strong>ways simple gener<strong>al</strong> vectors.<br />

time:*day-of-the-week-str1ngs.<br />

The hash table for day-of-the-week names.<br />

Variable<br />

Thus. time:month-string is defined (modulo error checking) as<br />

(defun month-string (month &option<strong>al</strong> modespec)<br />

(sgvref (mode-language-f<strong>et</strong>ch<br />

(or modespec .default-mode.) .month-strings.<br />

"Month name string")<br />

(1- month»)<br />

F<strong>et</strong>ching the vector and indexing into it can be useful if the vector is going to be used repeatedly,<br />

for instance for printing a directory listing.<br />

t<br />

~<br />

,..<br />

,.<br />

MC:<strong>NIL</strong>MAN:FNV 37<br />

23-()EC-H3


Time and Date 238 <strong>NIL</strong> Manu,tJ<br />

23.5.4 Timezones<br />

.t.. mezone. Variable<br />

The v<strong>al</strong>ue of this is the current timezone. It should be initi<strong>al</strong>ized in the <strong>NIL</strong> site<br />

initi<strong>al</strong>ization file to the correct v<strong>al</strong>ue; otherwise. it will be 5. which is Eastern time.<br />

time: t 1mezone-str .. ng &option<strong>al</strong> timezolle daylighl-savings-p<br />

This r<strong>et</strong>urns the canonic<strong>al</strong> three-charitcter string for the timczone. or nil if the name is not<br />

known to NIl ..<br />

(time:timezone-string 5 nil) => "EST"<br />

(time:timezone-string 5 t) => "EDT"<br />

(time:timezone-string 0 nil) => "GMT"<br />

lill1c:wlt' defintlts to the current timezone. and daylighh~m'il1g.'i-p to the v<strong>al</strong>ue of<br />

(time:daylight-savings-p).<br />

23.5.5 l\1iscellaneous Other Functions<br />

time: leap-year-p year<br />

R<strong>et</strong>urns t if year is a leap ye,)r. nil otherwise.<br />

t1me:dayl1ght-sav1ngs-p<br />

R<strong>et</strong>urns t if it is currently daylight savings time. nil otherwise.<br />

t1me:month-length month year<br />

R<strong>et</strong>urns the length of the month month in year.<br />

t 1 me : day 1 i 9 h t - s a vi n 9 s - t 1me-p hour day month year &option<strong>al</strong> limeZOlle<br />

R<strong>et</strong>urns t if the specified dHy/time is in dayJight savings time in the specified time/one<br />

(which defaults to the current timezone). nil otherwise. (The specified hour is assumed to<br />

be standard time.) Note <strong>al</strong>so section 23.5.6. page 239.<br />

time: day-of-the-wesk (day month year)<br />

R<strong>et</strong>urns the number of the day of the week of the specified date.<br />

t1me:ver1fy-date day m01lth year day-ofweek<br />

If day is a day within month which fell on dayofweek. this r<strong>et</strong>urns nil; otherwise. it<br />

r<strong>et</strong>urns a string describing the conflict<br />

time :moonphas8 &optionaJ ullivers<strong>al</strong>-time<br />

R<strong>et</strong>urns the phase of the moon decoded into five v<strong>al</strong>ues: the (zero-origined) number of<br />

the quarter. the day .. hour. minute. and second. The Quarters are (from 0 to 3) new<br />

moon, first quarter, fun moon, and last. quarter. This is presumably the uncorrected<br />

mean longitude.<br />

MC:<strong>NIL</strong>MAN:ENV 37<br />

23-DFC-83


<strong>NIL</strong> Manu<strong>al</strong> 239 Timc and Date<br />

t1me:pr1nt-moonphase quarter day hour minute second<br />

Prints the phase of the moon in a fonnat like "FM + 2Il3H.29M.57S.". The first field will<br />

be one of "NM", "FQ", "FM", or "LQ". Zero-suppression is perfonned on the other<br />

fields: for instance, "FM + 2D.29M.".<br />

time: pri nt-current-moonphase &option<strong>al</strong> (des/illation t)<br />

Similar.<br />

Note <strong>al</strong>so the g<strong>et</strong>-intern<strong>al</strong>-run-time and g<strong>et</strong>-intern<strong>al</strong>-re<strong>al</strong>-time functions. on page 223.<br />

2.15.6 \',uiations in nH)'light Savings Time<br />

The timezone objects ~Il. lIses to store information on particular time/ones include a function<br />

which may be lIsed to tell if a particular hour. day. month. and year (when intcrpr<strong>et</strong>ed as<br />

sLmdard time) is in daylight time. Most of the initi<strong>al</strong> timezone entries have nil in this component.<br />

which is taken to mean that the zone never uses daylight time. It may be necessary to patch this<br />

up: some functions and hacks arc presented here to aid in this.<br />

t 1me: zoneconv tilll('Z(Jlle<br />

If timezol1c is a timezone object (an object of type time:timezone), it is r<strong>et</strong>urned. If it is<br />

a number. then an existing timezone entry for that offs<strong>et</strong> in the list time: *timezones* is<br />

r<strong>et</strong>urned.· (Otherwise an error is sign<strong>al</strong>led.)<br />

If the daylight-savings-time predicate ~IL supplies is not appropriate for the site (or is just<br />

plain incorrect). it can be patched by<br />

(s<strong>et</strong>f (time:timezone-dst-rule<br />

(t ime: zoneconv timezone-offs<strong>et</strong>»<br />

'beandorfian-daylight-savings-time-p)<br />

where timezol1e-offsc/ is the offs<strong>et</strong> from GMT of the timezone in question, and beandorfiandaylight-savings-time-p<br />

the predicate which tells wh<strong>et</strong>her any particular hour in a particular<br />

year is in daylight savings time.<br />

t<br />

I<br />

I<br />

f<br />

f i<br />

~<br />

I<br />

t1me:regular-american-dayl1ght-savings-t1me-p hour day month year<br />

This r<strong>et</strong>urns t if hour, day. month, and year is b<strong>et</strong>ween 1 am of the last Sunday in April<br />

and 1 am of the last Sunday in October (see below).<br />

t1me:last-sunday-in-apr11 year<br />

R<strong>et</strong>urns the day of the month on which the last Sunday f<strong>al</strong>ls in April.<br />

t1me:last-sunday-1n-october year<br />

R<strong>et</strong>urns the day of the month on which the last Sunday f<strong>al</strong>ls in October.<br />

Computations like "last Sunday in April" are fairly easy to perfonn. To find the last dow day<br />

in a month. find the day-of-the-weck of the last day of the month. and subtract the number of<br />

days it takes to g<strong>et</strong> back to the desired day of the week. For instance,<br />

(defun last-sunday-in-april (year)<br />

(-& 30 (\\& (-& (+& 7 (day-of-the-week 30 4 year» 6) 7»<br />

111C 30 is the last day in April. 4 the month April: 6 is Sunday, and the 75 and arithm<strong>et</strong>ic with<br />

thcm doing modulus stuff. Obviously the arithm<strong>et</strong>ic can be simplified to<br />

~1C:NII.M:\N:ENV 37<br />

23-1)FC-83


Time and Date 240 Nil. Manuitl<br />

(-& 30


,1\ \1..muJl 241 Job/Process and System Information<br />

Iki.:.li.l'C '11 must use the V\1S time to d<strong>et</strong>ennine the abso1ute time. g<strong>et</strong>-univers<strong>al</strong>-time (nnd<br />

.," ~,::;c.., y,hich r<strong>et</strong>urn results based on that quantity. which is just about <strong>al</strong>l the time and date<br />

.' ~ "!,l;" In this ~c:ction) can r<strong>et</strong>urn an incorrect v<strong>al</strong>ue. Also. the quantities r<strong>et</strong>urned by elapsed-<br />

• _ .• ~.. I,<br />

t'rT".~ 'r. 1 F 22)) Jnd g<strong>et</strong>-intern<strong>al</strong>-reaJ-time (page 223) are based on this. meaning that if a shift<br />

'~, l"~ (lut of daylight time occurs and the VMS base time is changed, elapsed time measured<br />

.:', '_ ~,J the shift will be incorrect. There is a variable provided for telling <strong>NIL</strong> about two potenti<strong>al</strong><br />

\. -';,'-;.-v. ide COO\ cntions for bypassing this son of 10ssagc.<br />

t 1:1e: • sy s tem- time - k 1 udge*<br />

Variable<br />

'I hI'-. ma~ take on one of three v<strong>al</strong>ues,<br />

nil This is the default. It means that the \'\is hase time is <strong>al</strong>\\'ays the loc<strong>al</strong> time<br />

(r()[('nti<strong>al</strong>ly daylight time). and hence subject to compl<strong>et</strong>e lossage.<br />

:standard<br />

This means that the \'\1S base time is <strong>al</strong>ways based on the standard time for the<br />

current timclone.<br />

:gmt<br />

This means that the \,\15 hase time is GMT (implies never daylight time).<br />

f'l:hcr of the last two options eliminate the amhigous·hour and incorrect-elapsed-time<br />

r11 ·hkm' \\ hich might bc suffered otherwise. Of course. they mean that <strong>al</strong>l the \\1S<br />

uulJ[i~~ v.hich show dates and times won't work quite right. Oh well.<br />

I !~,: .1!1(1\ e \41flable is examined for conversion of <strong>al</strong>l \'MS intern<strong>al</strong> times into univers<strong>al</strong> time.<br />

\~..: ::\ \!~.::l~. fllr interpr<strong>et</strong>ation of the current time, if the ahove variable is nil. then the<br />

: ' : _:,::~' :\,f,;.. ll: ii,li"I"I(" is ~xdji"dlh:;d. (Thj~ is d lugi\.ai ll.tllU': u~\.:Jhh:f1ll1.:J by Cili.tO~IlCl ~(Jrlware<br />

,:


Job/Process and System Infonnation .<br />

242<br />

<strong>NIL</strong> Manu


Nil. Manu<strong>al</strong> -243 (\Hnpilation<br />

24. Conlpilation<br />

lompil<strong>al</strong>ion is essenti<strong>al</strong>ly the process of translating from one specification into another which<br />

is presumably more cfficient. and probably more low-level in some respects. The ~IL compiler<br />

translates LISP code into the VAX instnlctions neccssary to execute that code: some of these<br />

instructions may perfonn the task directly, while others may c<strong>al</strong>l functions or 1'\11. kernel<br />

subroutines to do it. In any event. the end result is intended to exclude the ~II. interpr<strong>et</strong>er from<br />

thc running of the program. The ~II. compiler does not output \iACR032 code or anything of the<br />

son: rather. it represents the code and data itself. and assembles the code. liSP objects<br />

referenced hy the code. and whatever other infonnation is needed to help construct that data.<br />

into a cOlI/pi/rc/ codr l11udule. This is what the module daw type represents.<br />

\\'hen the 'II compiler compiles a file. it first estahlishes the proper eJl\ironment for the<br />

compilation. as specified hy the file's attrihule list (described in section 19.8.6. page 205). That<br />

done. it reads and processes each fonn in the file. What it docs with each fonn depends on what<br />

the fonn is.<br />

( pro c 1 aim del-Sptc )<br />

If the y<strong>al</strong>ue of the fOl1n dcl-sprc can be d<strong>et</strong>ennined at compile-time. then the compiler<br />

will attempt to assert that proclamation for at least the duration of the compilation. Sec<br />

proclaim, page 46.<br />

(dec 1 are {dcP·spec}.)<br />

The del-specs are processed. and L1Ke effect for at least the remainder of the compilation.<br />

ut=dare ill uli~ UHllCXl i~ son of iikc prociaim with muitipic unevaiu3tea arguments:<br />

howe\er. this usage (non-loc<strong>al</strong> declarations) of declare is being phased out and subsumed<br />

by proclaim. It will be probably bc supported indefinitely. and will <strong>al</strong>so be accepting<br />

certain MACLISP-sty]c declarations which proclaim will not.<br />

(eva l-when k ... -J-lisl [onns . .. )<br />

If compile is a member of kwd-lisl. <strong>al</strong>l of the [onns are ev<strong>al</strong>uated then and there. Then,<br />

if load is a member of kwd-list. the [onns are recursivcly processed.<br />

(progn fonns . .. )<br />

fonns are recursively processed. Note that this is identic<strong>al</strong> to (ev<strong>al</strong>-when (load) fonns ... ),<br />

and upwards-compatible with the MACLlSP (progn 'compile fonns ... ) hack.<br />

(ccmp i 1 e r-l <strong>et</strong> bindings forms • .• )<br />

Establishes the bindings specified by bindings. then recursively processes fomls in that<br />

environment. See page 245.<br />

( de fun Ilame argUst <strong>et</strong>c . .. )<br />

(defun (name property-name) arglist <strong>et</strong>c ... )<br />

The function is compiled, and the appropriate assignment (function cell or putprop) will<br />

be put in the compiler's output file.<br />

( de f mac r 0 name <strong>et</strong>c.. . )<br />

(macro n<strong>al</strong>l1r lambda-list <strong>et</strong>c ... )<br />

Thc specified macro definition for name is added to the compilation environment. Then.<br />

the macro is compiled. so will be there when the compiled output file is loaded. It may<br />

not be depended on that name is defined in the liSP environment itself: only that code<br />

MC:NII.MAN:COMPIL 37<br />

23-I)EC-83


Compilation 244 Nil. Manu<strong>al</strong><br />

being compiled will have the macro run to produce the expansion. If it is necessary for<br />

the macro to actu<strong>al</strong>ly be defined (perhaps in order for it to be c<strong>al</strong>led from within other<br />

macros, as opposed to just expanded in code. being compiled). then the defmacro or<br />

macro fonn should be enclosed within an (ev<strong>al</strong>-when (compiJe ... ) ... } fonn.<br />

(defun name macro lambda-list <strong>et</strong>c .. • )<br />

Ine compiler whines at you and turns this into macro. This is provided to catch old<br />

MACUSJ> code which should probably use defmacro (or at the very least macro) instead.<br />

( de fun l1a1llP fe x p r lambda-lisl elc .• • )_<br />

"1l1e compiler barf.~ at you and turns this into a speci<strong>al</strong> form definition. C<strong>al</strong>ls to it from<br />

compiled code wil1 not work. If name is only around f(lr users to c<strong>al</strong>iintcracti\'cly,<br />

howe\'er, it might just function properly. This is provided only to brute-fi)ree through<br />

some ~f:\U IS]> progr~tms. Gener<strong>al</strong>1y. speci~ll fonns or frxprs should be rewritten as<br />

macros.<br />

( def u n Ilame <strong>al</strong>om elc ... )<br />

The function definition is assumed to be a MACI.ISP lexpr. It is transfonned appropriately,<br />

and compiled. after the compiler g<strong>et</strong>s through giving yuu a hard time.<br />

(defflavor <strong>et</strong>c)<br />

Code to perform the flavor definition at load tin;~ is generated. Addition<strong>al</strong>ly. declarative<br />

information is added to the compilation environment so that defm<strong>et</strong>hods will compile<br />

correctly, and the routines defined for the :outside-accessible-instance-variables can<br />

be compiled correctly.<br />

(defm<strong>et</strong>hod <strong>et</strong>c)<br />

Compiles the code for the defm<strong>et</strong>hod.<br />

a1lyth illg-else<br />

If anything-else is a macro caU or a c<strong>al</strong>l to a function the compiler has speci<strong>al</strong> rewrite<br />

information about, the macro expansion or rewrite is performed~ and the compiler tries<br />

again. Otherwise. anything-else will be ev<strong>al</strong>uated at load time. Currently this i~ done by<br />

compiling the expression. which eliminates load-time dependencies upon macros.<br />

There are various other fonns which implicitly do compile-time processing by vinue of how they<br />

are defined. rather than by the compiler recognizing them speci<strong>al</strong>ty. For instance, defstruct<br />

(currently) by default expands into the appropriate macro, function, and data definitions, with<br />

appropriate use of ev<strong>al</strong>-when. For this reason, the above list cannot be taken as being <strong>al</strong>linclusive.<br />

compile-file input-Jile &key package sel-dejaull-p<strong>al</strong>hname oUlpul:/ile dejiluil-pathname<br />

defaults<br />

Compiles input-jile, storing the vasl file in output-jile.<br />

If package is specified, then the file is read in in that package, in spite of what might be<br />

specified in the source file propcny list (see section 19.8.6, page 20S).<br />

The input-file is defaulted from the dejaull-p<strong>al</strong>lmame if any, and then from dejQuils.<br />

which should be a pathname defilUlts. If sel-dejiJull-p<strong>al</strong>llllame is not nil. then the default<br />

pamname of defoulls (which defaults to the v<strong>al</strong>ue of .toad-pathname-defaults., page<br />

201) is updated.<br />

MC:NII.MAN:COMPIL 37<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 245 Compilation<br />

OU/pul-file defaults to illpu/:/ile with a vasl file type (VMS extension of VAS).<br />

By speci<strong>al</strong> dispensation (to those of me who cannot g<strong>et</strong> out of the habit of using this<br />

feature), if exactly two arguments are given to compile-fife, then the first is the input file<br />

and the second is the output file. This is typicaUy used like<br />

(compile-file "[nil.io]iofun" "[nil.vas]")<br />

The CO:vt:vtO~ LISP definition of compile-file accepts only the keyworded argument outpu/­<br />

file.<br />

comfil e ...<br />

Alternate name for compile-file. CO\1\fO~ LISP defines the use of the name compilefile.<br />

hut not comfile, f(lr whatcver that is wonh. .<br />

compil e jUllction<br />

Compiles the interpr<strong>et</strong>ed (and in-core) definition of jUlic/ioll, in-core. That is.<br />

(defun fact (x)<br />

( i f (z e r 0 p


Intcraction Control . 246 <strong>NIL</strong> Manu<strong>al</strong><br />

switch. and these arc now obsoleledby usc of the optimize declaration. compiler-l<strong>et</strong> is<br />

still useful. of course. for communication b<strong>et</strong>ween macros. and that is its intended usc<br />

anyway.<br />

24.1 Interaction Control<br />

compiler: .messages-to-term1n<strong>al</strong>?<br />

Variable<br />

If this is not nil. then the compiler (compile-file and compile. and cvcn the I.SB-defincd<br />

function Isbcl [4}) will print out verbosely on thc termin<strong>al</strong>. If it is nil. nothing will bc<br />

printed. unless crrors occur. which is a separate can of worms. By default. this is t.<br />

24.2 Efficienc),'t Optitnilation .. and Benchmarking<br />

The current :,\11 compi1er is incredihly stllrid in some ways. 8asic<strong>al</strong>ly. it is an o\"crgrown<br />

one-pass code generator: it takes in a USP program. and spits out VAX machine language.<br />

m~lking liber<strong>al</strong> usc of LISP function c<strong>al</strong>ls and speciill subn.dtincs to handle things which arc too<br />

hulky or too complex for it to cod


NIl. Manu<strong>al</strong> 247 Efficiency. Optimization, and Benchmarking<br />

to briefly describe it more gener<strong>al</strong>ly. Basic<strong>al</strong>ly, a function c<strong>al</strong>l is handled hy the c<strong>al</strong>ler "creating"<br />

a c<strong>al</strong>l frame on the stack, filling it in. and then perfonning the actu<strong>al</strong> c<strong>al</strong>l. When such a frame<br />

is created, it can be recognized as such by a debugger (the current one doesn't know beans about<br />

it. but that is beside the point). and. while the arguments are being computed. it is possible to<br />

ten not only what function is aboul to be caned. but which arguments to it have been computed<br />

(and what their v<strong>al</strong>ues are). and which have not. If the compiler decides that it is ok to not have<br />

quile this much debugability. it might decide to try to compute some of the arguments as it<br />

creates the function c<strong>al</strong>l argument frame-this can save both space and time. but means you<br />

cannot tell what is going on while it is happening. No matler which way it does this. it may still<br />

have to push varying length blocks of constants on the stack. Even herc. therc arc spacc/time<br />

tradcofls to hc made: for instancc. helow some threshold. it takcs long.er to do a block -movc<br />

than to do a series of movcs/pushcs. And. therc is a decision as to what constant it is that g<strong>et</strong>s<br />

pushed: a marker (rccognizable by the debugger). or just zeroes (which can be done more<br />

efficicn t I y).<br />

Another area is that of ccrtain functions which can bc inline-coded. but which arc nonn<strong>al</strong>ly<br />

too hulky (0 make it worthwhilc under nonn<strong>al</strong> circumstances. memq is a finc example of this.<br />

Nonn<strong>al</strong>ly. memq is a minisuhr which will give a correctahlc crror if thc list is not a proper list.<br />

and which will d<strong>et</strong>ect circularity. If specd is myc important th,1I1 space and saf<strong>et</strong>y. however. the<br />

compilcr can in line-code the loop. Thc exact d<strong>et</strong>ennination is not only a filnction of the qu<strong>al</strong>ities<br />

specified with optimize. but <strong>al</strong>so the particular circumstances. If the list argument to memq is<br />

known at compile time. then the compiler can verify that it is a non-circular proper list. and thus<br />

no longer has to worry about the "saf<strong>et</strong>y" of the c<strong>al</strong>l. I f in addition the memq is being used for<br />

"plcuil:<strong>al</strong>C vaiuc·'. lh<strong>al</strong> is. in a comeXl iike<br />

( if (memq item lisl) liJell-do-lhis else-dc-this)<br />

whcre the specific v<strong>al</strong>ue of the memq does not matter, then the compiler can just code out the<br />

proper series of eq checks. How many it will be willing to do this for. is once again a<br />

space/time tradcoff.<br />

There is another class of optimization which can be perfonned: that is unfolding of common<br />

cases out of a more generic routine. For instance, the 1 + and 1- functions (page 74) are coded<br />

as minisubrs. They arc fairly generic, since they can accept arguments of any numeric type. But<br />

a common usage is with arguments which are fixnums. If space is not considered particularly<br />

important. but speed is. then the compiler can check to see if the argument is a fixnum. and if<br />

so do the addition or subtraction itself without g<strong>et</strong>ting into the generic routine. Because the code<br />

only does this on things it has verified as fixnums. and because it checks for overflow. this<br />

particular optimization does not involve "saf<strong>et</strong>y",<br />

Another aspect of "saf<strong>et</strong>y" is how likely the operation being perfonned is to produce<br />

som<strong>et</strong>hing "illeg<strong>al</strong>": in a LISP implementation like <strong>NIL</strong>. many objects like fixnums and characters<br />

have their data represented in the pointer. and operations on those objects just do operations on<br />

the pointers. For certain trivi<strong>al</strong> operations. of which many of the character functions (chapter 11)<br />

are characteristic, the compiler might choose to produce code which is a bit more circumspect<br />

ahout what it docs with pointers. what data-types of objects it might generate if given erroneous<br />

inputs. or possibly even wh<strong>et</strong>her it inline codes at <strong>al</strong>l. depending on what the result of an<br />

erroneolls input mig.ht imply. Take. for example. char-upcase: if this were inlinc-coded (it<br />

might not be in this particular version of i\1L). it effectively would be replacing part of the<br />

"address field" of the pointcr which is its argument. by som<strong>et</strong>hing elsc. If that argumcnt was not<br />

a character. but (say) a vector, it is quite likely that the resultant object would be unprintable.<br />

MC:NII.MJ\N:COMPIL 37<br />

23-DEC-83


Ftlicicncy. Optimi/<strong>al</strong>ion. and Benchmarking 248 <strong>NIL</strong> Manu<strong>al</strong><br />

givc garbage whcn examined. and. assuming the existence of a garbage-col1ectoT. cause the<br />

garbage-collcctor to fail in the middle of its operation. leaving thc LISP tot<strong>al</strong>ly useless. Many<br />

operations of. this nature. while having a moderate amount of overhead if done as function c<strong>al</strong>ls<br />

with error checking. can be made to at least not r<strong>et</strong>urn such objects with only a trivi<strong>al</strong> overhead.<br />

\\'hiIc in a sense this masks errors rathcr than d<strong>et</strong>ects them. having your lisp gct blown away by<br />

an iIleg<strong>al</strong> pointcr does not facilitate debugging either. In this regard, the things which heed the<br />

saf<strong>et</strong>y optimization qu<strong>al</strong>ity will gencr<strong>al</strong>ly not inline code at <strong>al</strong>l (depending on their trivi<strong>al</strong>ity) jf the<br />

safcty qu<strong>al</strong>ity is s<strong>et</strong> to 3. (Also. in gencr<strong>al</strong>. only high-level routines might offcr this choice: the<br />

:\11 fixnum-only routines. and character "subprimitives". will <strong>al</strong>ways inline-code. and not offer this<br />

safcty "option".)<br />

Thcrc ,Irc \·cry fe~' things which rccognilc thc compilation-speed optimi/


<strong>NIL</strong> Mdllu<strong>al</strong> 249 Illlroduction to thc STEV E editor<br />

25. Introduction to the STEVE editor<br />

25.1 Introduction<br />

STEVE is a gener<strong>al</strong> purpose screen oriented text editor based upon the EMACS editor. In many<br />

respects STEVE and E\1ACS arc identicaL with the primary difference being that STEVE is written in<br />

Nil. for the DEC VAX -11 series computers and can be c<strong>al</strong>led directly from the i'll. interpr<strong>et</strong>er.<br />

Those who arc familiar with EMACS will be able to usc STEVE immediately, and should skip to<br />

the end of this chapter, as the first part is meant to be an introduction to STEVE.<br />

25.2 G<strong>et</strong>ting Started<br />

There is one diflcrence h<strong>et</strong>w.een the editor environment and the rest of '" to he aware of.<br />

IkGllI~e the editor and \"\1S ha\"c conflicting uses for many of the control keys. the editor must<br />

nm in "pass<strong>al</strong>l" mode. This implies tJlat the nonn<strong>al</strong> interrupt cmrmands do not norm<strong>al</strong>ly work in<br />

tJle editor. So the first command to learn is tile ediLOr command to r<strong>et</strong>urn to \\!1atc\er you \.\ere<br />

doing hefore you entered the editor. It is a two key command typed hy holding down the<br />

"Control" ke) and pressing the "Z" key twice.<br />

Control-Z Control-Z R<strong>et</strong>urn-to-superior.<br />

Exit tJle editor and r<strong>et</strong>urn to whoever c<strong>al</strong>led it. This is tJle nonn<strong>al</strong> way to exit from<br />

STFVE.<br />

Now that you know how to exit the editor you may be curious how to enter it. Of course<br />

tJlis is not an editor command, but ratJ1er a 1'lL function.<br />

ad &option<strong>al</strong> wh<strong>al</strong>-Ia-edit<br />

Enters the editor, r<strong>et</strong>urning to whatever you were working on before. If you have not<br />

run the editor since starting <strong>NIL</strong> it will be compl<strong>et</strong>ely initi<strong>al</strong>ized with one empty buffer.<br />

or<br />

Norm<strong>al</strong>ly one types (ed) to the <strong>NIL</strong> interpr<strong>et</strong>er to g<strong>et</strong> into STEVE. what-ta-edit may be a<br />

path name (or string naming a file), or the name of a function. If given, the editor will<br />

try to find the file or function definition and l<strong>et</strong> you edit it: otherwise the argument is<br />

ignored. There arc editor commmands to find files and function definitions anyway, so<br />

the argument is not re<strong>al</strong>ly very importan~ except that it can be convenient. and can be<br />

used from programs.<br />

MC:<strong>NIL</strong>MAN;EDITOR 18<br />

23-DEC-83


Editing Files 250 <strong>NIL</strong> Manu<strong>al</strong><br />

25.3 Edit i ng Files<br />

The principle purpose of an editor is to create or modify a file. In broad outline an editor is<br />

used by reading a file into a buffer. modifying it somehow and then writing it back to some long<br />

term storage device. gener<strong>al</strong>ly a disk. Most of the editor commands arc concerned with modifying<br />

a buffer. and will be expained later. In order to understand the commands for reading and<br />

writing files one should know about the gener<strong>al</strong> structure of STEVE and its buffers.<br />

I <strong>NIL</strong> I<br />

I Editor I<br />

I \<br />

I \<br />

J Buffer-l I<br />

I Buffer-2 I<br />

I File-l I<br />

I File-2 I<br />

As the diagram shows. the editor runs inside Nil.. and contains any number of buffers, each<br />

of which is associated with a file. This diagram can be modified by creating a new buffer or<br />

kiHing one, or by changing the file associated with any buffer. There arc editor commands for <strong>al</strong>l<br />

of these operations. and for some more complex combinations of them. The editor <strong>al</strong>ways selects<br />

one buffer as the current buffer, and displays a section of it around the cursor.<br />

The fonnat of this display is· one of the features of an EMACS style editOr like STEVE, and is<br />

the reason it is c<strong>al</strong>led a "screen editOr".<br />

MC:<strong>NIL</strong>MI\N:EDITOR 18<br />

23-DEC-83


Nil. Manu<strong>al</strong> 251<br />

Editing Files<br />

This is a picture of what an editor I<br />

display might look like except that is is very'<br />

sm<strong>al</strong>l. ,<br />

Note that the cursor is at the end of ,<br />

the previous paragraph. ,<br />

I<br />

I<br />

I<br />

STEVE foo (LISP) disk:[cre]bar.lsp {3} --. I<br />

I<br />

I<br />

The hox in the diagram represents tllcedgcs of a ternlin<strong>al</strong> screen. The two paragraphs are<br />

thc contents of a huffer. The single line below tllat is c<strong>al</strong>led the mode line. It contains as l1Hch<br />

in f'(mnation ahout the currcnt sUite of the cditor as is convenient. From tllis we see that tlle<br />

buffcr is named "foo" and that it is associated with the file "disk:[cre}bar.lsp". The notation {3}<br />

after the file name indicates that the current version number is 3. If the file does not exist on<br />

disk the version number and tlle braces will be missing from tlle mode line. The star (*) on the<br />

right of the mode line indicates that the buffer has bcen changed so it is not the same as the file<br />

Oil Ul~~. Tile \.:Uln:1ll po~ition uf the cursor is at the end of the first paragraph. (On most<br />

tennin<strong>al</strong>s a cursor shows up as a blinking underscore or box. though this depends upon tlle exact<br />

type of tennin<strong>al</strong>. In this chapter we show the cursor as a underline (-) since it is fairly difficult<br />

to print a blinking cursor.)<br />

Under the mode line is a blank area of sever<strong>al</strong> lines. This is c<strong>al</strong>led the mode area and it is<br />

where most error messages and prompts are shown.<br />

We are <strong>al</strong>most ready to start expaining the individu<strong>al</strong> editor commands. The only other thing<br />

you should know first is how they arc typed. Most STEVE commands are either one or two<br />

character commands. Since one adds <strong>al</strong>phab<strong>et</strong>ic characters to the buffer simply by typing them<br />

(not that you know this y<strong>et</strong>) STEVE must not use <strong>al</strong>phab<strong>et</strong>ic characters for its commands. Instead<br />

the control characters are used. (The control characters are typed by holding down the "control"<br />

key and pressing some other key, just as the capit<strong>al</strong> l<strong>et</strong>ters are typed by holding down the shift.<br />

key.) Since there are not enough control keys for <strong>al</strong>l of STEVE'S commands it <strong>al</strong>so uses a m<strong>et</strong>a<br />

key. A M<strong>et</strong>a key is similar to a shift key or a control key. Now we can have the characters Ha U ,<br />

"A", "Control-A", "M<strong>et</strong>a-A", and "Control-M<strong>et</strong>a-A".<br />

Unfonunately most termin<strong>al</strong>s do not have a m<strong>et</strong>a key. Not to worry, though, STEVE is<br />

designed to work without i~ just as certain text justifiers are designed to work with tennin<strong>al</strong>s<br />

which have no lower case. Three commands are "bit-prefix" commands. Typing one of these will<br />

change the next character you type just as if you had been holding down the corresponding<br />

combination of control and m<strong>et</strong>a keys.<br />

MC:NII.MAN:EDITOR 18<br />

23-I)FC-83<br />

. -'- .:.-- - ... .. - ,-,:,. . ~ . ,~.- .<br />

·,,:.':'. ,;~, ~~ ~i~~£~~~)' ::~' ," .":: ":,,.:~: ,,' , ' .


Editing Files 252 Nil. Manu<strong>al</strong><br />

Altmode<br />

Prefix~M<strong>et</strong>a<br />

Pressing Allmode (marked SELECT or ESCAPE on some termin<strong>al</strong>s) will make the next<br />

character a "m<strong>et</strong>a" character. For example Allmode F(two characters) is the same as<br />

Al<strong>et</strong>a-F (one character).<br />

Control- Prefix-Control<br />

A<br />

Pressing Control;. t (control-uparrow) wilJ make the next character a "control" character.<br />

For example Control-t F (two characters) is the same as COlllrol-F (one character). On<br />

some termin<strong>al</strong>s. notably the vnoo. ((mtrol-t is typed as ('olllrol-- (control tilde);<br />

norm<strong>al</strong>ly. the A character is a shifted 6. so one holds down control, shift, and 6.<br />

Control-Z Prefix-Control-M<strong>et</strong>a<br />

Pressing ('emlrol-/. will make the next ch41r41cter be both a control and a m<strong>et</strong>a character.<br />

For example CUll/rol-/' F (two characters) is the s.lnle as COlllrol-Alela-F (one ch~lracler).<br />

All of these bit-prefix commands add the qu<strong>al</strong>ity to the next character. There is no problem<br />

with doing it twice. The two character sequences COlllrol-ZZ and ('oll1ro/-7. ('o11lrol-Z both 4lre<br />

read as ('olllro/-Alela-/..<br />

We are now ready swrt expaining the various editor commands. These are the commands you<br />

will use to create buffers and write files. All of these commands arc safe to use since they will<br />

notice if you are about to destroy any of your work and ask you if you re<strong>al</strong>ly want to do that.<br />

Control-X Control-F Find-File<br />

Find-File will prompt filr a file name and you should type it from the keyboard. If there<br />

is a buffer for that file then it wiU be selected and be the new current buffer. Otherwise<br />

a buffer is created for the file and the file is read in from disk if it exists there. Find­<br />

File is the most common way to read a file from disk. It creates a new buffer for each<br />

file which is convenient. When Find-FHe creates a buffer it lIses the file name without<br />

any extention as the buffer name. Since the name of each buffer must be unique this<br />

docsn't work when you are editing two files which have the same name but are on<br />

different directories or have different extensions (file types), so Find-File will notice if you<br />

are doing this and will ask you for a new buffer name to use.<br />

Control-X Control-S Save-File<br />

Save-File . writes the current buffer to its associated file, and changes the mode line to<br />

indicate that the buffer and file are now identic<strong>al</strong>. (This is not done until the output is<br />

compl<strong>et</strong>e. so if there is a disk error or some other error you will not think it has . been<br />

saved when it hasn't been.)<br />

Control-X Control-V Visit-File<br />

Control-X Control-R<br />

Visit-File is 1ike Find-File except that it re-uses the current buffer. destroying its contents.<br />

It is still safe since it will·offer to save it if any changes have been made to it<br />

Control-X Control-W Write-File<br />

Write~File writes the current buffer to a file, but .unlike save file it wi1J prompt you for<br />

the file name.<br />

MC:NII.MAN:EDITOR 18<br />

2]-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 253 Editing Files<br />

As an example. suppose that the screen looks like the diagram ahove. If you type Colllrol-X<br />

COl1tro/- H' (\\'rite-File) the editor will prompt you for a file name. Assume you want to save the<br />

file into disk:[cre]baz.lsp. You type "disk:[cre]baz.lsp". The screen will look like<br />

this:<br />

This is a picture of what an editor<br />

display might look like except that is is<br />

sm<strong>al</strong>l.<br />

Note that the cursor is at the end of<br />

the previous paragraph.<br />

STEVE foo (LISP) disk:[cre]bar.lsp {3} -- •<br />

Write File:disk:[cre]baz.lsp_<br />

I<br />

I<br />

verYI<br />

I<br />

I<br />

I<br />

I<br />

I<br />

I<br />

I<br />

I<br />

I<br />

I<br />

Notice that the cursor is temporarily placed in the mode area. After the command is<br />

compl<strong>et</strong>e it will r<strong>et</strong>urn to the text in· the buffer. The editor will fill in an incompl<strong>et</strong>e file<br />

specification for you. using the file specification associated with the huffer. In this example the<br />

liic mum.:


Modifying the huffer 254<br />

Nil. Manu<strong>al</strong><br />

This is a picture of what an editor I<br />

display might look like except that is is veryl<br />

sm<strong>al</strong>l._<br />

I<br />

Note that the cursor is at the end of I<br />

the previous paragraph.<br />

I<br />

I<br />

I<br />

I<br />

STEVE foo (LISP) disk:[cre]bar.lsp {I} -- I<br />

Wr it in 9 F i 1 e . . . I This lil1l' ...<br />

Wr i t te n SAl. LSP : 1 [CRE ]01 SK :<br />

I Theil litis line<br />

Nolice th<strong>al</strong> the cursor has r<strong>et</strong>urned to the huffer text ~Uld that the star (*) has been removed<br />

from the mode line to indicate that the buffer and file arc identic<strong>al</strong>. and that the version number<br />

h'l~ heen changed to 1. This is because the new file name did not exist on disk. Had the file<br />

been sm ed under its old name the version number would have been incremented by 1 from 3 to<br />

4. Fin<strong>al</strong>ly the file name in the mode area has been updated so that Save· File wm usc the new<br />

file name.<br />

25.4 l\lodifying the buffer<br />

25.4.1 The Simplest Commands<br />

As I hinted before. typing any <strong>al</strong>phanumeric character will add it to the buffer. In fact<br />

<strong>al</strong>most any character that you can type without holding down the control key will act like this.<br />

Also, the del<strong>et</strong>e (or rubout) key will del<strong>et</strong>e the last character before the cursor. If you can place<br />

the cursor where you want it and del<strong>et</strong>e· and insen characters then you are <strong>al</strong>ready able to make<br />

any editing change you have to. Since it is so simple to change characters in the buffeT, STEVE<br />

concentrates on commands to put the cursor where you want it quickly and easily. The first few<br />

such commands are:<br />

Control-F Forward-Character<br />

COlllro/-F moves the cursor forward one character in the buffer. (The end of a line<br />

counts as one character.)<br />

Control-B Backward-Character<br />

{ontrol- B moves the CUrsOT backward one character in the buffer.<br />

Control-N Down-Re<strong>al</strong>-line<br />

Move straight down to the next line.<br />

Control-P Up-Re<strong>al</strong>-line<br />

Muve straight up to the previous line.<br />

MC:NII.MAN:EDITOR 18<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 255 Modifying the buffer<br />

These are the commands to. move up down right and left.<br />

Now you know how to edit a file! If you can you should probably try to use STEVE to create<br />

a simple file and save it. Print it if you can and compare it to what you see on the screen. See<br />

what happens if you try to back up before the beginning of the buffer using Colllrol- B or<br />

Control-Po Type enough lines to fill up the screen (use R<strong>et</strong>urn to end each line) then a few<br />

more. What happens when the cursor is about to move onto the mode line? Now usc Control-P<br />

to move back.<br />

25.4.2 Now that you know the Simplcst Commands<br />

Now that you know the simplest commands there are many others that you should learn.<br />

There are some gener<strong>al</strong> facts ahollt ti1e editor which will help you g<strong>et</strong> more out of each command<br />

which 1 will expain first.<br />

25.4.2.1 Numcric Argunlcnts<br />

It is possible to give any command a numeric argument. The command or may not lise it.<br />

but you can <strong>al</strong>ways supply it. In fact, if you don't supply an argument an argument of one (1) is<br />

implied. There are sever<strong>al</strong> ways to specify an argument. In <strong>al</strong>l cases the numeric argument is<br />

typed before the command. The most gener<strong>al</strong> way to specify an argument is:<br />

Univer!<strong>al</strong>-Argument<br />

COlltrol-V followed by a positive or negative integer specifics ti1at integer as the argument<br />

for tile following" command. Cvmrul-V with no number specifics an argument of four (4).<br />

Control-V Alillus with no number is treated speci<strong>al</strong>ly as an argument of minus 1 (-l).<br />

Some commands treat Control-V with no number differently than Control-V 4.<br />

For termin<strong>al</strong>s with a m<strong>et</strong>a key it may be easy to usc the m<strong>et</strong>a-digit keys.<br />

M<strong>et</strong>a-O, M<strong>et</strong>a-I, ... , M<strong>et</strong>a-g, M<strong>et</strong>a-Minus<br />

Control-M<strong>et</strong>a-O, ... , Control-M<strong>et</strong>a-g, Control-M<strong>et</strong>a-Minus<br />

Auto-Argument<br />

Any of the M<strong>et</strong>afied numeric digits begin a numeric argument. It is just like Control-V<br />

followed by the digit. Notice that repeated m<strong>et</strong>a digits are multiplied tog<strong>et</strong>her.<br />

Control-O, ... , Control-g, Control-Minus<br />

Auto-Argument-Digit<br />

The control-digits end any previous digit and act as digits in an argumenL Thus Control-2<br />

Co Iltrol-3 is the argument twenty-three (23). Any arguments before or after a sequence of<br />

control-digits will be multiplied by the fin<strong>al</strong> control-digit argument. Because most<br />

termin<strong>al</strong>s do not send control-digits these must be specified using the uparrow bit-prefix<br />

(for instance, by typing Control-' 2), so in practice they are not used much. Note that<br />

the Control-'sI illus must be specified first<br />

If sever<strong>al</strong> arguments are specified they are multiplied tog<strong>et</strong>her. The primary use of multiple<br />

arguments is to type Control-V severa) times in a row. r .. ach Control-V multiplies the argument<br />

by four (4). So lOll/rol-V COll/rol-V is sixteen (16) and lVlltrol-V lOll/ml-U Cuntrol-V is sixtyfour<br />

(64). The. cursor movement commands treat the argument as a repeat count (as do most<br />

MC:<strong>NIL</strong>MAN:EDITOR 18<br />

23-DEC-8J


Modifying the buffer 256 <strong>NIL</strong> Manu<strong>al</strong><br />

commands where that· is me:.lningful). Some useful combinations are {olllro/-U ('omra/-V<br />

('(Jlltra/-F which moves forward about a quarte~ of a line, and COIl/ro/-V COlltro/-N which moves<br />

down four Iines~ You will. find many other "Cliches" or combinations of editor commands which<br />

you use automatic<strong>al</strong>ly to do one thing.<br />

25.4.2.2 Contro)-X<br />

As I said bef(lfe there arc not enough keys on a keyb~ard tbr <strong>al</strong>l of the commands. defined in<br />

STF\,J.:. The Al<strong>et</strong>a key is one way of g<strong>et</strong>ting more characters so STFVF can have a Jarge number of<br />

single character commands. But it is not enough. To g<strong>et</strong> e,"cn morc commands STF\T uses the<br />

key COlltml-X as a prefix chara


Nil. Manu<strong>al</strong> 257 Modifying the buffer<br />

If you type a question mark (7) while typing a Alcta-X command you will see a list of <strong>al</strong>l<br />

possihle ways to finish the command. This is typed in the upper part of the screen, over the text.<br />

(As soon as the Al<strong>et</strong>a-X command is finished. the text will be re-displayed.) If the list is longer<br />

than one screen fu 1 the word to. mo r e ." will appear on the last line above the mode line. Type<br />

5;pace to see the next screenful of commands. Type COlllrol-G to abort the entire Afela-X<br />

command. (There are sever<strong>al</strong> other commands which use the upper part of thc screen<br />

temporarily. All of these will print to.more." in the bottom line and expect either a ... S·pace to<br />

continue. or a COlllrol-G to abort. Any other character causes an abort. and is then used as a<br />

command.)<br />

A summary of speci<strong>al</strong> ,\I ela- X characters.<br />

Del<strong>et</strong>e<br />

E"icape<br />

Space<br />

Control-G<br />

Control-W<br />

Control-ll<br />

?<br />

Ruhout the last character showing in the command.<br />

Compl<strong>et</strong>es the command and separates arguments.<br />

Compl<strong>et</strong>es a word.<br />

Abort everything.<br />

Rubollt a word. Works while typing arguments <strong>al</strong>so.<br />

Start over. Rubout the entire M<strong>et</strong>a-X command. (Doesn't abort.)<br />

Help.<br />

Most commands which are nonn<strong>al</strong>ly executed using AINa-X are smart about their arguments.<br />

They can dctenlline how many you have typed and will prompt you for any that are required.<br />

Often it is easier to use ,Urla-X commands this way since the prompt will tell you what kind of<br />

urgumcnt hi typc. Si.iiiiC commands can d,,) cliinpkti(iil flif Y\JU "if ,,)ihcrw b(: hdp you lY 1-'(: tli(:<br />

arguments. The C()l1lrvl-JUela-X command is a variant of Alcro-X which is designed to lake<br />

advantage of this. The difference is that the command is executed as soon as it is compl<strong>et</strong>ed,<br />

either by Escape or Space. Otherwise it is exactly the same as Alela-X.<br />

25.4.2.4 ~farks and Regions<br />

Associated with each buffer is a ring which may store up to eight (8) marks. These are buffer<br />

pointers created by certain commands for future reference. There is a command to create a mark<br />

where the cursor is and a command to go to the last mark. and some other commands .. The text<br />

b<strong>et</strong>ween the cursor and the last mark is c<strong>al</strong>led the region. Many commands operate on this<br />

region.<br />

25.4.2.5 KUling and Un-killing<br />

Whenever more than one character is del<strong>et</strong>ed it is stored in a place c<strong>al</strong>led a kill-ring. Should<br />

you decide that it was a mistake to del<strong>et</strong>e it then you may r<strong>et</strong>rieve it with the un-kill command<br />

(Conlroi- Y). This <strong>al</strong>so l<strong>et</strong>s you copy text from one place to another, by killing it. moving the<br />

cursor and then un-killing it. To make severa) copics type COlllrol- Y scver<strong>al</strong> times. The<br />

command un-kill-pop CHela- Y) will r<strong>et</strong>rieve thc next to last peice of killed text. If A/r/a-}' is<br />

used right after lO1l1r(J/- Y or Alela-r the previous un-kill is del<strong>et</strong>ed first (Unlike ns E\1ACS.<br />

Alela- r can be used at any time.)<br />

MC:NII.MAN:E))ITOR 18


M(~or Modes 258 Nil. Manu<strong>al</strong><br />

25.4.2.6 List Oriented COlnmands<br />

A number of commands operate on "lists", These are nonn<strong>al</strong>ly defined as LISP lists with<br />

b<strong>al</strong>anced parentheses. This definition is controned by a syntax table and may vary in different<br />

major modes (see below). For example. in l.sa mode the characters { and } are· a type a<br />

parenthesis and will define a list The editor knows about doublcquote syntax for strings and<br />

vertic<strong>al</strong>-bar syntax for symbols,<br />

25.4.2.7 *more*<br />

A number of commands will overwrite the text on tJle screen, There is no need to worry.<br />

the text has not changed and will redisplayed when the current command is finished. If this<br />

merwrite fills the top part of the screen tJlen the word u.more." will be primed on tJle line<br />

above the mode-line. The editor will wait for you to rend tJle screen and type a space. The<br />

space will not be put into tJle buffer. it just indicates tJlat you arc ready to see me next screenful<br />

of informatio"'l. If you type lOl1lro/-G it will abort ~see below),<br />

25.4.2.8 Aborts<br />

When the editor is reading from the tennin<strong>al</strong> it usu<strong>al</strong>ly will abort if you type l ol1trol-G. lbe<br />

word "aborted" will appear in the mode area. This is a good thing to try if you are losing.<br />

though it doesn °t work in some places it should.<br />

25.5 Major Modes<br />

When editing different kinds of documents it is often convenient for some editor commands to<br />

behave slightly differently. For example, when editing a program it seems most useful to have<br />

the Tab key indent the current line so it lines up with the corresponding syntactic unit above it,<br />

but when editing a paper you want the tab key to indent for a paragraph. STEVE has a number<br />

of major modes which are designed for speci<strong>al</strong> kinds of editing. Most of the major modes are<br />

very similar, so there is no need to relearn much when you change modes.<br />

Bolio mode<br />

A mode bujJt on Text mode (see below) indendcd for sources to the text justifier Bolio,<br />

Knows about Bolio comments. Also assumes that Bolio is being used to document a Lisp<br />

program. so the paren echo hack is turned on and AI <strong>et</strong>a-. tries to find a function<br />

definition. The Control-M<strong>et</strong>a digits are used to change to that number font. Control­<br />

AI <strong>et</strong>a-· insens a "pop font" command.<br />

FUndament<strong>al</strong> mode<br />

The basic mode upon which most other modes are built Not used for much editing,<br />

since usu<strong>al</strong>ly there is a b<strong>et</strong>ter and more speci<strong>al</strong>ized mode for any particular job,<br />

Lisp mode<br />

For editing LISP programs. The principle features are that parentheses arc matched as<br />

they arc typed (try it. it is hard to explain) and that the Tab key knows how to indent<br />

for LISP code.<br />

MC:N1I.MAN:EDITOR 18<br />

23-I)I:C-83<br />

, ,<br />

...:.: ::/~ "~\.~~·i;.:. ~,., __ ..~..


<strong>NIL</strong> Manu<strong>al</strong> 259 Help and Self" I )ol'lllnentation<br />

LL mode<br />

Lisp Listener mode is not re<strong>al</strong>ly for editing documents. It simulates the liSP (or !'\IL) top<br />

level loop by ev<strong>al</strong>uating each top level fonn as soon as it is typed, and printing the result<br />

into the buffer. There are sever<strong>al</strong> reasons to use this mode for interactive testing.<br />

Because you are typing at the editor you have its full power to modify a form as you<br />

type it in. You are not limited to del<strong>et</strong>cing the last charactcrs typed as you would be<br />

nonn<strong>al</strong>ly. Even after a fonn is executed you may modify it and re-use it by backing up<br />

(with COlltrol-P), editing it, and then re-executing the fonn with !..tela-/. or by erasing<br />

and re-typing the last close paren. Fin<strong>al</strong>ly. there is a record of what you have done. and<br />

the results. You may save the buffer mid print it. You may add comments as you work.<br />

LSB mode<br />

For editing I.SB program~. The primary difference from 1 -isp mode is that the characters {<br />

and } arc <strong>al</strong>so treated as Parentheses.<br />

Test mode<br />

This should be dyked out. It is not useful except for debugging the editor itself.<br />

Text mC:',e<br />

For editing english (or german or french .. ,) text. T(lb is 1101111411 and ,Hela-. only searches<br />

the loaded buffers without trying to find the source file through the function definitinn.<br />

Obis may be wrong... comments?) Paragraph commands search for lines which begin with<br />

a white space character rather than for blank lines (as they do in program modes.)<br />

25.6 iieip and Seii Documentation<br />

STEVE has a sever<strong>al</strong> commands designed to hclp you when you don't know how do som<strong>et</strong>hing.<br />

The principle commands are Alela-? and COfllrol-Al<strong>et</strong>a-? which is the more gener<strong>al</strong> of the two.<br />

\\'hen you type {Oil trol-AI ela-? the editor will prompt you in the mode area with:<br />

Help (type? for options):<br />

You respond with a single character. The choices are<br />

A Apropos. (You type a Word to search for.)<br />

C Document a Character. (You type the character.)<br />

o Describe a command. (You type the command name.)<br />

K Document a Key. Identic<strong>al</strong> to C.<br />

S Syntax. (You type a character.)<br />

A (Apropos) prints <strong>al</strong>l paragraphs in the help file which contain a string.<br />

finding documentation on some concept. Also available through AI ela-X Apropos.<br />

It is useful for<br />

C (Character) finds the name of thc command that a key is bound to and then treats that just<br />

like D (Describe) would. Also available through Al<strong>et</strong>a-X Describe-Key. (Type the full name.<br />

AI ela-X Describe confuses compl<strong>et</strong>ion.)<br />

U (Uescribe) searches for a paragraph in the hclp file which contains the string in the first<br />

line of the paragraph. The help file is structured so that paragraph will he the documentation for<br />

that command when it is fully typed. If this is losing because you don't know the fun name of<br />

the command try Apropos instead. Also available through AI <strong>et</strong>a-X Describe.<br />

MC:NII.MAN:EDITOR 18<br />

23-DEC-H3


Glossary ofCommclllds 260 <strong>NIL</strong> Manu<strong>al</strong><br />

K (kcy) is anothcr namc filf C (Ch


Nil. MmlU<strong>al</strong> 261 Glossary of Commands<br />

Glossary Of STEVE commands<br />

25.7.J Speci<strong>al</strong> Character Commands<br />

Backspace<br />

Backward-Character<br />

Move the cursor backward one character or more if given an argument.<br />

Tab<br />

Insen a tab.<br />

Insert-tab (In non-LISP modes)<br />

Tab<br />

Indent-For-Lisp (In LISP modes)<br />

Indent tJle current line according to the nesting struclUre.<br />

Linefeed<br />

linefeed<br />

Break the current line and indent the next line. Equiv<strong>al</strong>ent to Rl'IUfll followed by Tab.<br />

R<strong>et</strong>urn<br />

Crlf<br />

Insert a line separator or just move. to the next line jf before two blank Jines.<br />

comme'1t ender if there is one.<br />

Altmode<br />

Bit-Prefix M<strong>et</strong>a<br />

Make the next character be a Alela character.<br />

Skips<br />

Rubout<br />

Backward-Del<strong>et</strong>e-Character (in non LISP modes)<br />

Del<strong>et</strong>es one character before point. If given an argument kills that many characters before<br />

nnint<br />

r •.-.•-<br />

25.7.2 Control Character Commands<br />

Control-Altmode Exit-Editor<br />

R<strong>et</strong>urn to whoever caned the editor, gener<strong>al</strong>ly the <strong>NIL</strong> interpr<strong>et</strong>er.<br />

Control-Space<br />

S<strong>et</strong>-or-pop-mark<br />

With no argument places a mark at point. With an argument pops the last mark and<br />

goes to it<br />

Control-;<br />

Indent-for-comment?<br />

Inserts a comment on the current line or adjusts the placement of an existing comment.<br />

Control-<<br />

Mark-Beginning<br />

Place a mark at the beginning of the buffer.<br />

Control-=<br />

What-Cursor-Position<br />

Prints the X and Y coordinates of the cursor on the screen, the current character and the<br />

number of characters before point and the percentage of the file which that is. Line<br />

separators count as two characters since that is how many they occupy in a file. See<br />

Count - Lines - Region<br />

Control-><br />

Mark-End<br />

Place J mark at the end of the buffer.<br />

MC:<strong>NIL</strong>MAN:EOITOR 18<br />

23-DFC-83


c<br />

Glossary of Commands 262<br />

Control-@<br />

S<strong>et</strong>-or-pop-mark<br />

With no argument places a mark at point. With an argument pops the Jastrnark and<br />

goes to it.<br />

Control-A<br />

Beginning-Of-Line<br />

Move the cursor to the beginning of the current line.<br />

Control-B<br />

Backward-Character<br />

Move the cursor back one character or more if given an argument.<br />

Control-C<br />

Exit-Editor<br />

R<strong>et</strong>urn to whoever c<strong>al</strong>led the editor. gener<strong>al</strong>ly the ~Il interpr<strong>et</strong>er. CCJIllrol-C should<br />

inlerrupt ule editor as it docs in the rest of 'II. but because the editor must be in Pass<strong>al</strong>l<br />

mode that is not possible.<br />

Control-D<br />

Del<strong>et</strong>e-Character<br />

I :>C1<strong>et</strong>e the character that the cursor is on.<br />

Control-E<br />

End-Of-'.ine<br />

Mo\'e the cursor to the end of the cunent line.<br />

Control-F<br />

Forward-Character<br />

Move the cursor forward one character or more jf given an argument.<br />

Control-G<br />

COlltroJ-G will abort the editor if it is reading from the termin<strong>al</strong>.<br />

Control-H<br />

R~ckw~rd-C~aracter<br />

Just like Comru/-B. COlllro/-H is Backspace in seven-bit ASCII.<br />

Control-I<br />

Tab<br />

Conlrol-! docs whatever Tab would do. In Lisp Mode and its derivatives (see major<br />

modes. below) this indents according to the syntax of text as a LISP program. In non-Lisp<br />

modes this is a norm<strong>al</strong> Tab.<br />

Control-J<br />

Indent-New-Line<br />

Equiv<strong>al</strong>ent to R<strong>et</strong>urn followed by Tab. Ends the current line and indents the next line.<br />

Control-K<br />

Kill-Line<br />

Kill to the end of the current line. If the cursor is at the end of a line it kills the line<br />

separator. With an argument kills that many lines.<br />

Control-L<br />

New-Window<br />

Dear the screen and redisplay everything. Useful if the screen is garbaged somehow· (for<br />

example if someone sends you mail). The window is moved to put the cursor in the<br />

middle of the screen. With an argument puts the cursor that many lines from the top of<br />

the screen. With a negative argument counts fTomthe bottom of the screen.<br />

Control-M<br />

CRLF<br />

Insert a line separator or just move to the next line if before two blank lines. Skips<br />

comment ender if there is one.<br />

Control-N<br />

Down-Re<strong>al</strong>-Line<br />

Move the cursor straight down one line or more if given an argumenl<br />

Control-Q<br />

Open-Line<br />

Puts a R<strong>et</strong>urn right after the cursor. With an argument creates that many blank lines.<br />

MC:NII.MAN:EDITOR 18<br />

23-DEC-83


Nil. Manu<strong>al</strong> 263 Glossary of Commands<br />

Control-P<br />

Up-Re<strong>al</strong>-line<br />

Move the cursor up one line or more if given an argument.<br />

Control-Q<br />

Quoted-Insert<br />

The next character is treated as an <strong>al</strong>phanumeric character regardless of what it is. This is<br />

how to put control characters into the buffer. Al<strong>et</strong>a characters cannot be put in the<br />

buffer, because they cannot be in <strong>NIL</strong> strings.<br />

Control-R<br />

Reverse-I-Search<br />

Increment<strong>al</strong>ly search backward through the buffer for a string.<br />

Control-S<br />

I-Search<br />

I ncrement<strong>al</strong>ly search the butler for a string.<br />

Control-T<br />

Transpose-Characters<br />

Exchange the character before the cursor with the character at the cursor.<br />

Control-U<br />

Univers<strong>al</strong>-Argument<br />

Read an argument for the next command.<br />

Control-V<br />

Next-S·.reen<br />

Move the window and the cursor forward <strong>al</strong>most one scrccnful. The last two lines of l.he<br />

window arc now the top two lines. With a numeric argument moves the window and<br />

cursor that many lines.<br />

Control-W<br />

Kill-Region<br />

Kill the region b<strong>et</strong>ween point and mark and save it in the kill ring.<br />

Control-X<br />

Prefix-Character<br />

COil tro 1-X is a prefix character. Type any character after it for a two character command.<br />

Control-Y<br />

Un-Kill<br />

G<strong>et</strong> the most recent kill out of the kill ring and insen it in the buffer. With an argument<br />

N g<strong>et</strong>s the Nth kill. With just Control-Vas an argument. it leaves the cursor before the<br />

un-killed text.<br />

Control-Z<br />

Bit-Prefix Control-M<strong>et</strong>a<br />

Read the next character as a Control-AI <strong>et</strong>a character.<br />

Control-\<br />

Prefix-M<strong>et</strong>a<br />

Read the next character as a Al<strong>et</strong>a character.<br />

Control-]<br />

Abort-Recursive-Edit<br />

R<strong>et</strong>urn from a recursive edit without doing anything more.<br />

Control- ....<br />

Bit-Prefix Control<br />

Read the next character as a Control character.<br />

Control-Rubout<br />

Backward-Oel<strong>et</strong>e-Hacking-Tabs<br />

Like Rubout except that a Tab is first expanded into spaces. This is useful for indenting<br />

things. In Lisp modes Rubout and Control-Rubout are interchanged.<br />

MC:NII.MAN:EDITOR 18<br />

23-DEC-83


Glossary of Commands 264' <strong>NIL</strong> MmlU<strong>al</strong><br />

25.7.3 M<strong>et</strong>a Key commands<br />

M<strong>et</strong>a-Linefeed<br />

Indent-New-Comment-Line<br />

Equiv<strong>al</strong>ent to Control-N M<strong>et</strong>a-:<br />

M<strong>et</strong>a-R<strong>et</strong>urn<br />

Back-To-Indentation<br />

Put the cursor on the first non white-space character in the current line. (Tabs and spaces<br />

arc white-space.)<br />

M<strong>et</strong>a-Altmode<br />

Start a minibuffer.<br />

Minibuffer<br />

M<strong>et</strong>a-#<br />

Change-Font-Word<br />

Change the font of the pre\,ious word~<br />

M<strong>et</strong>a-(<br />

Make-parens<br />

Enclose the next I.ISI) exprcs..~ion in parens. With an argument enclose that many I.ISP<br />

expressions.<br />

M<strong>et</strong>a-)<br />

Move-Over-Right-Paren<br />

Move past the next close parenthesis. then do a I.illr/ecd.<br />

M<strong>et</strong>a-.<br />

Oefun-Search-All-Buffers<br />

Find a defun. In some modes this will look at the subr object to find the module a<br />

grovel around to find and load the file where the function is defined. In most text modes<br />

(other than bolio) it just searches the loaded buffer.<br />

M<strong>et</strong>a-;<br />

lnoent-t"or-comment?<br />

Inserts a comment on the current line or adjusts the placement of an existing comment.<br />

M<strong>et</strong>a-<<br />

Goto-Beginning<br />

Put the cursor at the beginning of the buffer.<br />

M<strong>et</strong>a-=<br />

Count-Lines-Region<br />

Prints the number of lines b<strong>et</strong>ween point and mark in the mode area. Also prints the<br />

number of buffer characters. b<strong>et</strong>ween point and mark (counting the line separator as one<br />

character. See What-Cursor-Position.)<br />

M<strong>et</strong>a-><br />

Goto-End<br />

Put the cursor at the end of the buffer.<br />

M<strong>et</strong>a-?<br />

Describe-Key<br />

Reads a key from the keyboard and prints its documenta~on.<br />

M<strong>et</strong>a-A<br />

Backward-Sentence<br />

Move. to the end of the previous sentace.<br />

M<strong>et</strong>a-B<br />

Backward-Word<br />

Backup one word. (With an argument backs up that many words.)<br />

M<strong>et</strong>a-C<br />

Capit<strong>al</strong>ize a word.<br />

M<strong>et</strong>a-O<br />

Kill the next word.<br />

Uppercase-initi<strong>al</strong><br />

Kill-word<br />

MC:<strong>NIL</strong>MAN:EDITOR 18<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong><br />

Glossary of Commands<br />

M<strong>et</strong>a-E<br />

Forward-Sentance<br />

Move the cursor to the end of the current sentance.<br />

M<strong>et</strong>a-F<br />

Forward-Word<br />

Move over one word. With an argument moves over that many words.<br />

M<strong>et</strong>a-H<br />

Mark-Paragraph<br />

Put point at the beginning of a paragraph and mark at the end.<br />

M<strong>et</strong>a-I<br />

Insert-Tab<br />

Puts a tab into the buffer. Alela-I doe's not change in Lisp modes.<br />

M<strong>et</strong>a-J<br />

Equiv<strong>al</strong>ent to COlllrol-N Afcla-:.<br />

Indent-New-Comment-Line<br />

M<strong>et</strong>a-K<br />

Kill-Sentence<br />

Kill the sentence after the cursor.<br />

M<strong>et</strong>a-L<br />

Lowercase-Word<br />

Convert the next word to 4111 lowercase characters.<br />

M<strong>et</strong>a-M<br />

Back-To-Indentation<br />

Move the cursor to the first non white-space character in the current line.<br />

M<strong>et</strong>a-N<br />

Oown-Comment-line<br />

If the current line has a blank comment del<strong>et</strong>e it. rlllen move to the next line and add<br />

or adjust the comment start in the correct column.<br />

M<strong>et</strong>a-p<br />

Up-comment-Llne<br />

If the current line has a blank comment del<strong>et</strong>e it. Then move to the previous line and<br />

add or adjust the comment start in the correct column.<br />

M<strong>et</strong>a-R<br />

Move-To-Screen-Edge<br />

With an argument move to the beginning of that line on the screen. With a negative<br />

argument count from the bottom. With no argument move one third from the top.<br />

M<strong>et</strong>a-S<br />

Center-Line<br />

Centers the non white-space characters in the current . line.<br />

M<strong>et</strong>a-T<br />

Transpose-Words<br />

Exchange the words before and after the cursor.<br />

M<strong>et</strong>a-U<br />

Uppercase-Word<br />

Conven the next word to <strong>al</strong>l upper case characters.<br />

M<strong>et</strong>a-V<br />

Previous-Screen<br />

Move point and the window back so the two top lines become the two bottom lines.<br />

With an argument move that many lines.<br />

M<strong>et</strong>a-W<br />

Copy-Region<br />

Put the text b<strong>et</strong>ween point and mark in the kill ring but do not del<strong>et</strong>e it from the buffer.<br />

M<strong>et</strong>a-[<br />

Backward-Paragraph<br />

Move to the beginning of a paragraph. In Lisp modes a paragraph begins with a blank<br />

linc. Otherwise a paragraph begins with a line that starts with a white-space character.<br />

M<strong>et</strong>a-\<br />

Oel<strong>et</strong>e-Horizont<strong>al</strong>-Space<br />

Del<strong>et</strong>e any spaces or tabs around the cursor.<br />

MC:NII.Mt\N:EDITOR 18<br />

23-I)EC-8]


I<br />

Glossary of Commands 266 <strong>NIL</strong> Manu<strong>al</strong><br />

Forward-Paragraph<br />

Move to the end of a paragraph.<br />

M<strong>et</strong>a~]<br />

M<strong>et</strong>a- Del<strong>et</strong>e-Indentation<br />

A<br />

Join the current line to the previous line and del<strong>et</strong>e white space as appropriate. Leaves<br />

the cursor where the line separator wa~ . so a Linefeed undoes the effect of AI ela- t .<br />

M<strong>et</strong>a--<br />

Buffer-Not-Modified<br />

Clears the flag which says the current buffer has been changed. The star (*) in the mode<br />

line wiIJ be erased. He careful with this command: usc it only when you arc slire there<br />

have not been any dMnges to the buffer that yuu want saved.<br />

M<strong>et</strong>a-Rubout<br />

Backward-Kill-Word<br />

K ill the word befor the cursor.<br />

25.7.4 Control-l\l<strong>et</strong>a Commands<br />

Control-M<strong>et</strong>a-Backspace Mark-Defun<br />

Put point at the beginning of a defun and mark at the end.<br />

Control-M<strong>et</strong>a-Linefeed Indent-New-Comment-Line<br />

Equiv<strong>al</strong>ent to COl1lro/-N Alelo-,' .<br />

Control-M<strong>et</strong>a-R<strong>et</strong>urn Back-lo-Indentation<br />

Move the cursor to the first non white-space character in the current line.<br />

Control-M<strong>et</strong>a-(<br />

Backward-Up-List<br />

Move backward to next enclosing open parenthesis.<br />

Control-M<strong>et</strong>a-)<br />

Forward-Up-List<br />

Move forward to next enclosing dose parenthesis.<br />

Control-M<strong>et</strong>a-;<br />

Kill-Comment<br />

Kill the entire comment field on the current line.<br />

Control-M<strong>et</strong>a-? Editor-Help<br />

Self documentation function. Type a single character (one of A, C, D. K, S, or 7) to<br />

select which type of help you want.<br />

Control-M<strong>et</strong>a-@<br />

Mark-Sexp<br />

Put the mark at the end of the next LISP expression.<br />

Control-M<strong>et</strong>a-A<br />

Beginning-Of-Defun<br />

Backup to the beginning of the current or previous defun. Does not require matched<br />

parentheses or a compl<strong>et</strong>e defun.<br />

Control-M<strong>et</strong>a-B<br />

Backward-Sexp<br />

Move backward over one USP expression.<br />

Control-M<strong>et</strong>a-C<br />

Compile-Sexp<br />

_ Compile the current defun. Only works. for <strong>NIL</strong> code. lbe compiled function is loaded<br />

into the current <strong>NIL</strong><br />

Control-M<strong>et</strong>a-D<br />

Down-List<br />

Move to the inside of the next list in the buffer.<br />

MC:NH .MAN:EDITOR 18<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 267 Glossary of Commands<br />

Control-M<strong>et</strong>a-E<br />

End-Of-Defun<br />

Move to the end of the current or next defun. Does not require matched parentheses or<br />

a compl<strong>et</strong>e defun.<br />

Control-M<strong>et</strong>a-F<br />

Forward-Sexp<br />

Move forward over one LISP expression.<br />

Control-M<strong>et</strong>a-H<br />

Mark-Defun<br />

Put point at the beginning and mark at the end of the current defun.<br />

Control-M<strong>et</strong>a-J<br />

Indent-New-Comment-Line<br />

Equiv<strong>al</strong>ent to lOl1lrol-N Al<strong>et</strong>a-: .<br />

Control-M<strong>et</strong>a-K Kill-Sexp<br />

K ill the next J .lSI> expression.<br />

Control-M<strong>et</strong>a-M Back-To-Indentation<br />

Move the cursor to the first non white-space character in the current line.<br />

Control-M<strong>et</strong>a-N<br />

Forward.-L i st<br />

Move forward over one list.<br />

Control-M<strong>et</strong>a-O Split-Line<br />

Break a line at the cursor and indent the second h<strong>al</strong>f so it starts in the same column.<br />

Control-M<strong>et</strong>a-P<br />

Backward-List<br />

Move backward over one list.<br />

Contro/-M<strong>et</strong>a-Q<br />

Indent-Sexp<br />

Apply tab to every line in the LISP expression fol1owing the cursor except. for the first<br />

line.<br />

Control-M<strong>et</strong>a-R<br />

Reposition-Window<br />

Try to place the beginning of the current dcfun at the top of the window without moving<br />

the cursor. Does not require b<strong>al</strong>anced parentheses.<br />

Control-M<strong>et</strong>a-T<br />

Transpose-Sexps<br />

Exchange the previous and next USP expressions.<br />

Control-M<strong>et</strong>a-U<br />

Backward-Up-List<br />

Move backward to the previous enclosing open parenthesis.<br />

Control-M<strong>et</strong>a-V<br />

Scroll-Other-Window<br />

In two window mode scrolls the other window forward.<br />

lines.<br />

With an argument scrolls by<br />

Control-M<strong>et</strong>a-W<br />

Append-Naxt-Kill<br />

If the next command is a kill command the previous kit1 wi11 be appended to it, even if<br />

it would not otherwise be. Has no effect if the next command is not a kill command.<br />

Control-M<strong>et</strong>a-X<br />

Instant-Extended-Command<br />

Read an extended (named) command from the keyboard and execute it. If compl<strong>et</strong>ion<br />

finishes the command name it will be executed instantly. without waiting for a Relurn.<br />

Control-M<strong>et</strong>a-[<br />

Beginning-Of-Defun<br />

~1o\'c to the beginning of the current or previous defun.<br />

MC:NII.MAN:EDITOR 18


, .... e "r,<br />

Glossary of Commands 268 Nil. Manu<strong>al</strong><br />

Control-M<strong>et</strong>a-]<br />

End-Of-Defuo<br />

Move to the end of the current" or next dcfun.<br />

Control-M<strong>et</strong>a- .... Del<strong>et</strong>e-Indentation<br />

Join the current line to the previous line and del<strong>et</strong>e whitc space as. appropriate. Leaves<br />

the cursor where the line scparator was, so a Lillefeed undocs the cffect of Col1lro/­<br />

Alela-t .<br />

Control-M<strong>et</strong>a-Rubout Backward-Kl11-Sexp<br />

Kill the I.ISP cxpression bcfhre me cursor.<br />

25.7.5 Control-X Commands<br />

Control-X Control-A Toggle-Auto-Fil1-Mode<br />

\\'ith no arg. togglcs auto fin mode. With a negativc arg. turns it off. With a positive<br />

arg. turns it on and s<strong>et</strong>s Fill Column to that number.<br />

Control-X Control-B L i st-Buffers-<br />

I -ists <strong>al</strong>l huffers and their meljor modes.<br />

Control-X Control-Z<br />

Exit-Editor<br />

R<strong>et</strong>urn to whoever c<strong>al</strong>led the editor. gener<strong>al</strong>ly the <strong>NIL</strong> interpr<strong>et</strong>er.<br />

Control-X Control-D Directory"-Display<br />

I.ist <strong>al</strong>l versions and types of the current file. With an argument reads a pathname and<br />

t.· , . t ••<br />

II:'\.!) <strong>al</strong>l fll\;~ WIIU,':U Illdu.:n u.<br />

Control-X Control-F Find-File<br />

Find-File wiH prompt for a file name and you should type it from the keyboard. If there<br />

is a buffer for that file thcn it will be selected and be the new current buffer. Otherwise<br />

a buffer is created for the file and the file is read in from disk if it exists therc. Find­<br />

File is the most common way to read a file from disk. It creates a new buffer for each<br />

file which is convenient. When Find-File creates a buffcr it uses the file name without<br />

any extention as the buffer name. Since the name of each buffer must be unique this<br />

doesn't work when you are editing two files which have the same name but are on<br />

different directories, or have different extensions (file types) so Find·File will notice if you<br />

are doing this and will ask you for a new buffer name to use.<br />

Control-X Tab<br />

Indent-Rigidly<br />

With an argument shifts <strong>al</strong>l lines in the region right (or left if negative) that many<br />

columns.<br />

Control-X Control-l Lowercase-Region<br />

Conven <strong>al</strong>l characters b<strong>et</strong>ween point and mark to lower case.<br />

Control-X Control-N S<strong>et</strong>-Go<strong>al</strong>-Column<br />

COlllroi-N and COJllro/·P try to move to the go<strong>al</strong> column if there is one. With an<br />

argument removes the go<strong>al</strong> column. Otherwise s<strong>et</strong> it to the current cursor position.<br />

Control-X Control-O Del<strong>et</strong>e-Blant-Lines<br />

Del<strong>et</strong>e <strong>al</strong>l blank Jines foUowingpoint, and if the current is blank del<strong>et</strong>e <strong>al</strong>l blank lines<br />

before it.<br />

MC:NIl.MAN:EDITOR 18<br />

23-DEC-83


NIl. Manu<strong>al</strong> 269 Glossary of Commands<br />

Control-X Control-P Mark-Page<br />

Put point (.It the beginning and mark at the end of the current page.<br />

Control-X Control-Q S<strong>et</strong>-File-Read-Only<br />

With positive argument s<strong>et</strong>s file read only.<br />

With negative argument s<strong>et</strong>s buffer read only.<br />

With zero argument <strong>al</strong>lows any access.<br />

Control-X Control-R Visit-File<br />

Visit-File is like Find-File except that it re-uses the current buffer. destroying its contents.<br />

It is still safe since it will oITer to save it if any changes have been made to it.<br />

Control-X Control-S Save-File<br />

Sa\c-File writes the current buffer to its associated file. and changes the mode line to<br />

indicate that the buffer and file are now idemic<strong>al</strong>. (This is not done until the output is<br />

compl<strong>et</strong>e. so if there is a disk error or some other error you wiJI not think it has been<br />

StH'ed when it hasn't been.)<br />

Control-X Control-T Transpose-lines<br />

Exchange the cllrrent and previous lines.<br />

Control-X Control-U Uppercase-Region<br />

Convert <strong>al</strong>l characters b<strong>et</strong>ween point and mark to upper case.<br />

Control-X Control-V Visit-File<br />

Visit-File is like Find-File except that it fe-uses the current huffer. destroying its contents.<br />

Control-X Control-W Write-File<br />

Write-File writes the current buffer to a file. but unlike save file it will prompt you for<br />

the file name.<br />

Control-X Control-X Exchange-Point-And-Mark<br />

Put point where mark is and mark where the point was.<br />

Control-X Altmode<br />

Ev<strong>al</strong>uate the symbol n + n.<br />

this does the right thing.<br />

Re-Execute-Minibuffer<br />

Alera-X and some other commands s<strong>et</strong>q + appropriately so<br />

Control-X #<br />

Change-Font-Region<br />

S<strong>et</strong>s the font number of the region to the argument. Good for Bolio at least<br />

Control-X (<br />

Start-Kbd-Macro<br />

Begins defining a keyboard macro.<br />

Control-X 1<br />

One-Window<br />

Make the current window fill the entire screen and discard <strong>al</strong>l other windows.<br />

Control-X 2<br />

Two-Windows<br />

Split the current window into two windows. Can create any number of windows until<br />

they g<strong>et</strong> two sm<strong>al</strong>l.<br />

Control-X 3<br />

View-In-Other-Window<br />

Split the current window into two windows but stay in the top h<strong>al</strong>f ..<br />

Control-X 4<br />

Visit-In-Other-Window<br />

Combines Find-File and two window mode. Asks for a file to find. then displays it in a<br />

MC:NII.MAN:FDITOR 18<br />

2J-DFC-83


Glossary of Commands 270 Nil. Manu<strong>al</strong><br />

new second window.<br />

Control-X;<br />

S<strong>et</strong>-Comment-Column<br />

S<strong>et</strong>s the comment column to the current cursor column. Comment commands try to start<br />

comments in the comment column.<br />

Control-X =<br />

What-Cursor-Position<br />

Shows the X and Y coordinates of the cursor on the screen. the current character and<br />

how far through the buffer you are.<br />

Control-X A<br />

Append-lo-Buffer<br />

Adds the text of region to the end of another buffer.<br />

Control-X B<br />

Select-Buffer<br />

Asks for a buffer name and creates or selects CI buffer of that name.<br />

Control-X F<br />

S<strong>et</strong> Fill Column<br />

S<strong>et</strong>s the fin column to be the argument. if given. or else the current cursor position.<br />

Control-X G<br />

G<strong>et</strong>-Q-Reg<br />

Asks for the name of a LISP variable and tries to interpr<strong>et</strong> its v<strong>al</strong>ue as. text to inscrt into<br />

the buffer.<br />

Control-X H<br />

Mark-Whole-Buffer<br />

Put point at the beginning of the buffer and mark at the end.<br />

Control-X K<br />

Kill-Buffer<br />

R~:trl" :t h~lff~r n~rne'~nd km~ th~! buffer.<br />

Control-X l<br />

Count-lines-Page<br />

Prints the number of lines in the current page in the mode area.<br />

Control-X 0<br />

Selects the next window.<br />

Other-Window<br />

Control-X T<br />

Transpose-Regions<br />

Transposes two regions defined by point and the last three marks.<br />

Control-X X<br />

Put-Q-Reg<br />

Asks for a lisp variable and saves the text in the current region there. Designed to be<br />

undone with Gct-Q-Reg (Contro/-X G).<br />

Control-X [<br />

Previous-Page<br />

Move point to the previous page boundary.<br />

Control-X]<br />

Next-Page<br />

Move point to the next page boundary.<br />

Control-X Rubout Backward-Kill-Sentence<br />

Kills text to the previous end of sentence.<br />

MC:NlI.MAN:EDITOR 18<br />

23-DEC-83


Nil. Manu<strong>al</strong> 271 Glossary of Commands<br />

25.7.6 M<strong>et</strong>a-X Commands<br />

Apropos<br />

Scarches the documentation for a string and prints <strong>al</strong>l paragraphs which contain the string.<br />

Auto-Fill-Mode<br />

Toggle auto fill mode. With an explicit argument. turn it on if positive. and off if<br />

negative. I forg<strong>et</strong> what 0 does. Unfortunately this docs not change the mode line. It will<br />

in thc next vcrsion.<br />

Bolio-Mode<br />

Bolio mode is huilt on Text mode. hut has features from Lisp mode. In particular Alcla·.<br />

docs a Find Function and the parenthesis b<strong>al</strong>ancing hack is turned on. Comments are<br />

Bolio comments. Also. ('ollfro/·,Hcta·digit and C0I11ro/·AlcIO·* insert a Co1l1rol·F followed<br />

hy themselves. as font switching commands.<br />

Comment-Region<br />

Adds comments to the beginning of each line b<strong>et</strong>ween point and mark. Can be undone<br />

with :\IcIO·X Ullcommel11·Region. Won't work for languages with a comment terminator (l<br />

think).<br />

Compile<br />

Compiles the file associated with the current buffer. With a pathname argumcnt compiles<br />

that file instead. Asks if you want the file loaded when done.<br />

Copy-Made-Line<br />

Copy the first non·blank line of the last buffer selected to the first line of this buffer. An<br />

argument is the name of a buffer to use instead.<br />

Del<strong>et</strong>e-File<br />

Read~ a file name and del<strong>et</strong>es it. Asks for confinnation.<br />

Describe<br />

Reads a command from the keyboard and searches for documentation on it.<br />

Describe-Char-Syntax<br />

Rcads a character and lists its editor syntax. For nonn<strong>al</strong> characters just type the character<br />

and R<strong>et</strong>urn. For speci<strong>al</strong> chractcrs you must type its symbolic name in accordance with<br />

the currcnt readtable.<br />

Ev<strong>al</strong>uate<br />

Reads and ev<strong>al</strong>uatcs one <strong>NIL</strong> fonn. Prints the v<strong>al</strong>ue in the mode area. Pass<strong>al</strong>l mode is<br />

turned off during ev<strong>al</strong>uation for saf<strong>et</strong>y.<br />

Fundament<strong>al</strong>-Mode<br />

Scts the major mode for the current buffer to Fundament<strong>al</strong>.<br />

Help-M<strong>et</strong>a-X-Commands<br />

Lists the AI ela· X commands. This will probably go away and be subsumed under some<br />

more powerful help function.<br />

Kill-loc<strong>al</strong>-Variable<br />

Removes the currcnt buffer's loc<strong>al</strong> binding of a variable.<br />

Kill-Same-Buffers<br />

Asks for each buffcr wh<strong>et</strong>her to kill it or save it.<br />

MC:NII.MAN:EDITOR 18<br />

23·DEC·83


Glossary of Commands 212 Nil. Manu<strong>al</strong><br />

Kill-Variable<br />

Attempts to makunbound some variable. May change or go away.<br />

lisp-Mode<br />

Scts the major mode of the current buffer to Lisp. Turns on the parcnthesis echo hack<br />

and some other features.<br />

ll-Mode<br />

S<strong>et</strong>s the major mode of the current buffer to LL (Lisp Listener). Lisp Listener mode is<br />

built on l.isp mode. but has the feature that a defun is ev<strong>al</strong>uated and printed into the<br />

buffer when it is finished. It acts like the top-level loop in many ways. except <strong>al</strong>l input<br />

m1d output is san~d in a buffer.' You <strong>al</strong>so g<strong>et</strong> to usc Tab and the other editor features<br />

which help typing f .JSP forms.<br />

loc<strong>al</strong>-Bind<br />

Bind some variable to some v<strong>al</strong>ue when in the current buffer. lf prompting fi)r input this<br />

will tell you what the current vaJue is.<br />

lSB-Mode<br />

Makes the current major be LSH.<br />

<strong>al</strong>so parentheses.<br />

Make-loc<strong>al</strong>-Variable<br />

Like h<strong>al</strong>f of Loc<strong>al</strong>-Rind.<br />

Very similar to Lisp mode. except that { and }. arc<br />

Makes the variable loc<strong>al</strong> to tl1e current huffer .. but doesn't<br />

change its v<strong>al</strong>ue. Not sure if this is useful. it. is an attempt to sort of be compatible with<br />

EMACS.<br />

Name-KBD-Macro<br />

If there is a keyboard macro this will <strong>al</strong>low you to name it and to put it on a key. Asks<br />

for the key. then asks for confinnation about that.<br />

Overwrite-Mode<br />

This is not a major mode. It is <strong>al</strong>so not finished. It is supposed to make self-inserting<br />

characters overwrite the existing characters rather that move them over. This much works,<br />

but there is some other hair which is unimplemented.<br />

Query-Replace<br />

Replace <strong>al</strong>l occurances· after point of the first argument with the second argument. Asks<br />

about each replacement. "?" will list the options in the mode area. Space does the<br />

replacement, Rubout does not. Escape exits immediately. Period (.) makes the replacement<br />

then exits, and Comma makes the replacemen~ then waits for a Space before continuing<br />

(so you can see the change before moving to the next one).<br />

Rename-Buffer<br />

Change the name of the current buffer.<br />

Renam.e ... Fi le<br />

Takes two file name arguments. Renames the first to the second.<br />

Reparse-Mode-line<br />

Res<strong>et</strong> the m,ljor mode and <strong>al</strong>l loc<strong>al</strong> variables from the file property list of the file<br />

associated with the current buffer.<br />

Replace<br />

Replace <strong>al</strong>l occurrences of the first argument with the second argument. Acts<br />

MC:NII.Mt\N:EDITOR 18<br />

23-DEC~83


<strong>NIL</strong> Manu<strong>al</strong> 273 Glossary of Commands<br />

instantaneously (wen. as fast as a V AX can go) and leaves the cursor where it was. Note:<br />

Currently the cursor is left at where the last string was replaced.<br />

Save-A11-Fi·les<br />

L<strong>et</strong>s you save any modified buffers. Asks about each one separately.<br />

S<strong>et</strong>-Key<br />

The first argument is a Key and the second is a binding. Control-X keys can be specified<br />

like (# \Control-X # \Control-B). Keys should be specified is accordance with the current<br />

readtable.<br />

S<strong>et</strong>-Variable<br />

s<strong>et</strong>s a LISP \ariable to some v<strong>al</strong>ue.<br />

S<strong>et</strong>-Visited-Fi1ename<br />

Changes the file name associated with the current buffer. but docs not change the buffer<br />

or write any files.<br />

Test-Mode<br />

1\ major mode build on LL mode (Lisp Listener) but with pass<strong>al</strong>1 turned off. Not fe<strong>al</strong>ly<br />

Slife why I did this. except to test the editor. since Pass<strong>al</strong>l is ofT in 1.1. mode when<br />

reading and ev<strong>al</strong>uating a fonn.<br />

Text-Mode<br />

The major mode for editing text. Also try Bolio mode.<br />

Trace-Current-Defun<br />

Tries to tind the name of the current defun and caU trace on it. Given and argument will<br />

trace that function instead.<br />

Uncomment-Region<br />

Tries to remove comments from a region of commented code. Meant to be used with<br />

Alela-X Comment-Region.<br />

Underline-Region<br />

If the tennin<strong>al</strong> supports underlining change the visible part of the region so it is<br />

underlined. Waits for you to type a space, then reverts to the nonn<strong>al</strong> display and l<strong>et</strong>s<br />

you continue.<br />

View-Buffer<br />

Shows the contents of a buffer in screenfuls.<br />

View-File<br />

Shows the contents of a file in screenfuls. Until the <strong>NIL</strong> garbage collector works this is<br />

much less efficient than visiting the file since <strong>al</strong>l of the lines are wasted compl<strong>et</strong>ely.<br />

View-Kbd-Macro<br />

Shows the sequence of characters in a keyboard macro in the mode area.<br />

View-Mail<br />

This is just a hack which runs View-File over the VMS mail file sy s$l og in: rna i 1 . rna i.<br />

If it docsn'r work, don't use it<br />

View-Variable<br />

Prints the v<strong>al</strong>ue of a LISP variable. Doesn't barf if the variable is not bound. 'Other than<br />

that it is no b<strong>et</strong>ter than Afcta-X Ev<strong>al</strong>uate.<br />

MC:<strong>NIL</strong>MAN:EDJTOR 18<br />

23-DEC-83


Extending the Editor 274 <strong>NIL</strong> Manu<strong>al</strong><br />

What-Page<br />

Prints the current page number and ·1ine number.<br />

Write-region<br />

Writes the text b<strong>et</strong>ween point and mark to a file.<br />

supplied.<br />

Asks for the file name if it is not<br />

25.8 Extending the Editor<br />

E\'en1U(Jl1y the intern<strong>al</strong>s of the editor wi11 he documented pr<strong>et</strong>ty compl<strong>et</strong>ely. Currently the<br />

intern<strong>al</strong>s arc suhjcct to change. so any ex(ention may be broken by futurc changes to tJle editor,<br />

1-10we\·cr. ,IS any haCKer knows. ,l program does not change a1l that quickly... So one may<br />

assume th,H most of the intern<strong>al</strong>s will not. change much. ttNol being documented" means that I<br />

don't know which parts will change and which parts won't. su you pays your money ,md you<br />

klkcs your chances.<br />

25.8.1 Editor Functions<br />

An editor function ;, just a <strong>NIL</strong> function in the package STEVE. Currently the name of the<br />

function as given in th'smanu<strong>al</strong> or with the Describe-Key command is the name of the <strong>NIL</strong><br />

function. unless th<strong>al</strong> conflicts with some other ~ll. function. (There has been some t<strong>al</strong>k of adding<br />

a consistent prefix or suffix to aU editor commands to distinguish them from other interna1 editor<br />

r.~_<br />

• VA<br />

example the I.lSP fonn (steve:forward -word) will move the cursor forward one word. just like<br />

Alela;.F would. Numeric arguments arc passed in the glob<strong>al</strong> variable steve:*argument •.<br />

steve: ed1tor-b1 nd-Icey key-sequence binding &option<strong>al</strong> motir-name<br />

key-sequence may be either a character object or a list containing two character objects. It<br />

is ev<strong>al</strong>uated. The code field of these characters should not be an ASCII control character;<br />

use the bits field to select a control character. A list is interpr<strong>et</strong>ed as a two character<br />

command using a prefix character (gener<strong>al</strong>ly Control-X). The binding is not ev<strong>al</strong>uated. It<br />

may be a function name, an editor command macro specification or a key indirection.<br />

Nonn<strong>al</strong>ly the binding is a function name to c<strong>al</strong>l when the key is typed. The function will<br />

be c<strong>al</strong>led with no arguments.<br />

If the binding is a character object the binding for that character object is used instead.<br />

This is only used for binding Control·/ to Tab. so it may not be very robust<br />

A list is used to define an editor command macro. The car of the list is a function and<br />

the cdr. is a list of arguments. When the editor is reading the key as a command the<br />

function is c<strong>al</strong>led and its v<strong>al</strong>ues are r<strong>et</strong>urned as the "key" and command. This is hairy<br />

and should not be used lightly. Look at the code for numeric arguments and bit-prefixes<br />

to see how it can be used.<br />

lbe mude--Ilame is used to find the binding table for that major mode. The major mode<br />

must be declared when this is executed. The default is to usc the current major modc.<br />

which is nonn<strong>al</strong>ly fundament<strong>al</strong> when not in the editor. i.e. when linking· <strong>NIL</strong>.<br />

MC:NII.MAN:EDITOR 18<br />

2J-I)EC-83


<strong>NIL</strong> Manu<strong>al</strong> 275 Extending the Editor<br />

If the binding is a symbol then it is <strong>al</strong>so defined as a Alcta-X command. Not sure if this<br />

is good but thaCs the way it is right now.<br />

steve: ed1 tor-defun-Key key-sequence name &body fonns<br />

A cross b<strong>et</strong>ween defun and editor-bind-key. Dcfuns name to be a no argument function<br />

with a body of jonus and binds it to key-sequence using editor-bind -key. There is some<br />

debate about wh<strong>et</strong>her to use this function or not.<br />

A number of the editor functions take option<strong>al</strong> arguments which arc intended to make it<br />

easier to usc them from I"II. code. Usu<strong>al</strong>1y these


Extending thc Editor 276 <strong>NIL</strong> Manu<strong>al</strong><br />

steve: make-l1 ne buffer previous Ilext&option<strong>al</strong> sIring<br />

R<strong>et</strong>urns a line in buffer b<strong>et</strong>ween prel'ious and next containing siring. If next is nil this<br />

will be the end of the buffer.<br />

steve: buffer spec &key :create<br />

spec may be a pathname. a buffer name (as a string). a buffer or an edit-cursor. The<br />

v<strong>al</strong>ue is either nil or a buffer. which is found or created using spec. The keyword<br />

argument cre<strong>al</strong>e d<strong>et</strong>ermines jf the buffer is created when it docs not exist <strong>al</strong>ready. 'lbe<br />

default is to creatc a new buffer.<br />

steve:po1nt 5P(,(, &key cre<strong>al</strong>e<br />

l.ikc buffer except r<strong>et</strong>urns an edit-cursor. The argument ('reat(' controls wh<strong>et</strong>her a butfer<br />

is crcated in order to build the edit-cursor. (If there is () buffer then an edit-cursor will<br />

a1ways be r<strong>et</strong>urned. regardless of the v<strong>al</strong>ue of creau. An edit-cursor must hm"c a bufl'er.)<br />

The edit-cursor may Of may not have a window.<br />

steve: paint-selected spec &kcy cre<strong>al</strong>e<br />

l.ike point except that the edit-curSOf is selected" as the current cursor and its huffer is the<br />

current buffer.<br />

This last function uses primitives which are useful in their own right.<br />

steve:select-po1nt point<br />

Make poi11l he the current cursor and its huffcr the current huffer.<br />

steve: select-po1nt-1n-current-w1 ndow poini<br />

Like select-point except the window of the current cursor is stolen. This is usu<strong>al</strong>ly the<br />

right way tp sclect a cursor.<br />

SonIC common operations on lines. These arc done carefully, so as to do the right thing at<br />

the beginning and end of the buffer.<br />

steve: line-next line<br />

R<strong>et</strong>urn the line after line or nil if at the end of the buffer. This is a macro generated by<br />

defflavor.<br />

steve: line-previous line<br />

R<strong>et</strong>urn the line before line or nil if at the beginning of the buffer.<br />

steve:nth-next-l1ne line n<br />

R<strong>et</strong>urn the line n lines after line ~ If the cnd of the buffer is reached. the last line in the<br />

buffer is r<strong>et</strong>urned. If n is 0 the first argument is r<strong>et</strong>urned. If n is negative, moves<br />

backward.<br />

steve:nth-prev1ous-l1ne lille n<br />

Like nth-next-line except moves up for positive n.<br />

MC:Nl'.MAN:EDITOR 18


n .-<br />

@"<br />

<strong>NIL</strong> Manu<strong>al</strong> 277 Extending the Editor<br />

Some operations on bps.<br />

:advance-pos n<br />

Ask the bp to advance by 11 chars. Line separators count as 1 character. Bombs back to<br />

the editor top level at beginning and end of buffer.<br />

: move lille Il<br />

Place the bp pointing to the nth character of line.<br />

:g<strong>et</strong>-char<br />

R<strong>et</strong>urn the character that the bp points to.<br />

:g<strong>et</strong>-char-forward<br />

R<strong>et</strong>urn the character that the bp points to and advance over it.<br />

:peek-char-backward<br />

R<strong>et</strong>urn the character before theme that the bp points to.<br />

:g<strong>et</strong>-char-backward<br />

R<strong>et</strong>urn the character hefore the one that the bp points to hackup to point to it.<br />

Note the unpleasant asymm<strong>et</strong>ry of names. However. none of these can be interpr<strong>et</strong>ed as standard<br />

stream messages.<br />

25.8.3 Other Functions and Conventions<br />

Editor errors.<br />

steve:save-<strong>al</strong>l-f11es<br />

This is the Al<strong>et</strong>a-A' S<strong>al</strong>'e-All-Files function. It may be c<strong>al</strong>led from outside the editor if the<br />

editor is broken, and may be able to save your buffers.<br />

steve: ed-lose [oml<strong>al</strong>-string &restv [onnat-args<br />

Abort any operation immediately. Print the Jonnat-string and ring the bell. then r<strong>et</strong>urn to<br />

the editor top-level. The [orowt-string is printed in the mode area. Pass<strong>al</strong>1 mode is<br />

turned off while aborting to the top level, so if a bug causes a rep<strong>et</strong>itive error you can<br />

escape by typing Conlrol-C at the right instant. Keep trying, it works, but it may take a<br />

few tries.<br />

steve: ed-warn [onnat-string &restv [ormat-args<br />

Like ed -lose except the ben is not rung. In gener<strong>al</strong> ed -lose is used when the editor<br />

d<strong>et</strong>ects an error. and ed -warn is used for predictable events, like the Colllro/-G abort out<br />

of a command reader. I fee1 that if the user has <strong>al</strong>ready done som<strong>et</strong>hing to cause an<br />

abort h('/she will not want to hear how ups<strong>et</strong> the editor is. The bell is to bring attention<br />

to som<strong>et</strong>hing unexpected.<br />

MC:<strong>NIL</strong>~1AN:EDITOR 18<br />

23-DEC-S3


1':Xlcnding thc Editor 278 Nil. Manu<strong>al</strong><br />

steve: ed-w8rn1 ng jiJnnl1l-s/ring &restv jbnll<strong>al</strong>-args<br />

Print ji)rm<strong>al</strong>-slrillg in the mode area, and continue. Docs not cause an exit to the editor<br />

top-level. but continues any operation in progress.<br />

steve: wi th- no- pas s811 &body fom7s<br />

Execute fonns with the termin<strong>al</strong> not in pass<strong>al</strong>l mode. S<strong>et</strong>s up an unwind-protect form so<br />

an abort is o.k.<br />

steve: *ed1tor-dev1ce-mode*<br />

Variable<br />

The editor s<strong>et</strong>s the tennin<strong>al</strong> to pass<strong>al</strong>l mode only if this variable is t. If you write an<br />

editor function which turns pass<strong>al</strong>l 011' and on yuu should <strong>al</strong>ways usc the fimn:<br />

(send termin<strong>al</strong>-io :s<strong>et</strong>-device-mode<br />

:pass<strong>al</strong>l steve:*editor-device-mode*)<br />

Arguments.<br />

steve:argument?<br />

Use the fonn (steve:argument?) to d<strong>et</strong>ermine if any numeric a 'gument was given.<br />

steve:c-u-only?<br />

R<strong>et</strong>urns t if the argument was Colllroi-U with no number.<br />

steve:rea1-arg-sup?<br />

(and (steve:argumentl) (not (steve:c-u-only71»)<br />

But more efficient in 'code and runtime.<br />

steve: buffer-beg1 n1 &option<strong>al</strong> bp<br />

Test wh<strong>et</strong>her bp (or the current cursor) is at the very beginning of the buffer.<br />

steve: buffer-end? &option<strong>al</strong> bp<br />

Similar; test for the end of the buffer.<br />

steve: f1 rst-l1 n8? &option<strong>al</strong> bp<br />

R<strong>et</strong>urns t if the bp is anywhere in the first line of its buffer.<br />

steve: 1 ast-l1 n8? &option<strong>al</strong> bp<br />

An<strong>al</strong>ogous.<br />

steve: not-buffer-begin &option<strong>al</strong> bp<br />

steve: not-buffer-ef)d &option<strong>al</strong> bp<br />

steve: not-f1rst-l1 ne &option<strong>al</strong> bp<br />

steve: not-18st-11 ne &option<strong>al</strong> bp<br />

R<strong>et</strong>urn to the editor top level if the bp fails the given test. Otherwise do nothing.<br />

MC:NII.t\1AN:EDITOR 18<br />

23-DEC-83


NIl. Manu<strong>al</strong> 279 Extending the Editor<br />

Redisplay<br />

steve:make-screen-1mage<br />

This is poorly named. It used to be different. Now it is the redisplay entire and<br />

compl<strong>et</strong>e. Just c<strong>al</strong>l it and the screen will be redisplayed. (If a character has been typed it<br />

will exit immediately.)<br />

steve:s<strong>et</strong>up-mode-area<br />

Generate and print a current mode line.<br />

Some functions use the upper area of the screen to print things. The redisplay must he<br />

told that tJlis has happened. This is handled by using sever<strong>al</strong> speci<strong>al</strong> tlmclions to position<br />

tJ1e cursor and to do terpri. It is possihle that this will he changed and that there will be<br />

a speci<strong>al</strong> stream which keeps track of such things. I was sick of defining speci<strong>al</strong> purpose<br />

streams when I got to this.<br />

steve:overwrite-start<br />

Begin to overwrite the display. If there has b~en some overwriting of the screen since the<br />

last redisplay s141rt after it. Otherwise start at the top.<br />

steve:overwr1te-home<br />

Start at the top <strong>al</strong>ways.<br />

steve:overwrite-terpr1<br />

Move the cursor to the next overwrite line. 'r11is will do .more* processing as needed.<br />

steve:overwrite-done<br />

Always c<strong>al</strong>l this when finished with an overwrite display. This makes overwrite-start begin<br />

in the right place if c<strong>al</strong>led before a redisplay.<br />

Reading from the tennin<strong>al</strong>.<br />

steve :mx-prompter function jonn<strong>al</strong>-string &restv fonnat·args<br />

Prompts in the mode area using jonnat-slring and jonnat-args, then reads from the<br />

tennin<strong>al</strong> using junction. Handles C011lrol-G and has some addition<strong>al</strong> intern<strong>al</strong> hair which<br />

<strong>al</strong>lows compl<strong>et</strong>ing functions to be defined. May be modified to handle ? as a help key<br />

somehow.<br />

steve:read-f11e-name<br />

Can only be used as an argument to mx-prompter. Reads a file name and r<strong>et</strong>urns it as<br />

a string. Some day this will do compl<strong>et</strong>ion.<br />

steve:read-buffer-name<br />

Only for usc as an argument to mx -prompter. Will do buffer name compl<strong>et</strong>ion and<br />

respond to? Example:<br />

steve:(mx-prompter ,'read-burfer-name "Foo(-a): " faa)<br />

MC:NIl MAN:EDITOR 18<br />

23-DEC-83


The Patch Facility 280 <strong>NIL</strong> Manu<strong>al</strong><br />

26. l"he Patch Facility<br />

The patch facility provides a means by which a program (whatever that might mean) may be<br />

increment<strong>al</strong>ly updated: it essenti<strong>al</strong>ly a bookkeeping operation. and is primarily designed for<br />

providing the updates necessary for a dumped-out system. In the context of the patch facilIty.<br />

such a program unit is c<strong>al</strong>led a patchable system: usc of thc term system in this context means<br />

the same thing, but may not in other contexts. (NlI. has no more sophisticated system-building<br />

tools currently. <strong>al</strong>though it cenainly has whatever primitives might be needed.)<br />

The design of the !\Il. patch facility is origin<strong>al</strong>ly derived from the uSP M:\CIII~F I.ISP patch<br />

fllcility [121. That was first implemented from scrcttch in \1:\('1 lSi>. and some time later the<br />

\1.\( 'lISP \·ersinn was copied and modified to he more appropriate for ;\11. This is noted because<br />

there arc \ariou~ design flaws and misfcatures of the filciJity. which arc inherited and are due in<br />

part to the application of the techniques used to a different programming environment. A future<br />

release should have a redesigned facility which will correct these things.<br />

P<strong>al</strong>chah1c systems have both m(~;or and millor .version numbers. The major ve/sinn number<br />

corresponds to a compl<strong>et</strong>e new system generation. like when a :\11 maintainer (one of' the authors)<br />

loads lip a new :'\11. having incorporatcd any fixes into the source files and rccompiled any files<br />

which needed it. '1l1e minor version number is incremented whenever an update is made. The<br />

updates are maintained on disk: each one corresponds to a particular file (a patch file) which<br />

implements the fix (usu<strong>al</strong>ly. some function and variable definitions the same as in a newer version<br />

of some source file). A patch directory is maintained for each major version number: it<br />

ClIUtll\'·ICtic~ (ami JC~I iiJc!'l) iilc Pi.lll.:itc~ fur ciu.:h minor vcr~ion numher. Finaiiy. each p<strong>al</strong>chabie<br />

system has a p<strong>al</strong>ch system definitiol1 Jife. which primarily provides <strong>al</strong>l kinds of default attributes<br />

about the system. which include the current version number and the location of the otlier files in<br />

the filesystem (thus the only place a pathname need ordinarily be specified to the patch facility is<br />

when pointing at the patch system definition file to define the patch system origin<strong>al</strong>ly).<br />

A typic<strong>al</strong> cycle of usage for the authors might thus look like this. We have a freshly-made<br />

<strong>NIL</strong>. say version 175 (the Release 0 version). As bugs are found. they are accumulated into patch<br />

files. One person might accumulate sever<strong>al</strong> fixes over the course of a day into a single patch file.<br />

This might then be the update which makes Lisp 175.0 become Lisp 175.1. Exportation of the<br />

patch directory and the patch files for Lisp 175 to other sites will then <strong>al</strong>low them to be loaded<br />

by other dumped-out <strong>NIL</strong>s of Lisp version 175. Eventu<strong>al</strong>ly. one of us will decide that the<br />

changes are too far-reaching or too numerous. and decide to go on to another system version.<br />

This norm<strong>al</strong>ly involves ensuring that aU updated sources are recompiled, loading up a new <strong>NIL</strong>,<br />

and telling the patch system we want a new major version number. Note that the last is<br />

independent. conceptu<strong>al</strong>ly, from loading up a new <strong>NIL</strong>: it is an operation which says that what<br />

we have on disk is a new version. A conceptu<strong>al</strong> bug in the distributed <strong>NIL</strong> is the case with which<br />

one may load up a <strong>NIL</strong> and increment the version number. Unless one is actu<strong>al</strong>ly modifying the<br />

files which g<strong>et</strong> loaded. onc's site should remain at <strong>NIL</strong> version 175. If it does not. then a bug<br />

report referring to the <strong>NIL</strong> version is meaningless to us.<br />

At the end of section 26.4. page 285. is a description of a more common usage of the patch<br />

system. where it is used for a system which is /luI dumped out.<br />

MC:NII.MAN:PATCH 25<br />

23-DEC-83<br />

. . ,<br />

0~j~}l~~


Nil. Manu<strong>al</strong> 281 User Functions<br />

26.1 User Functions<br />

load - pa tchas &rest poorly-desiglled-keywords<br />

Loads patches for the specified (or <strong>al</strong>l) systems. This takes keyword arguments in a nonstandard<br />

fashion. <strong>al</strong>though that is expected to be changed incompatibly in the future. All<br />

of them except for :systems take 110 arguments. They are:<br />

:systems list-afsystems<br />

Load patches for the specified list of patch systems. rather than <strong>al</strong>l those currently<br />

defined.<br />

:verbose<br />

Be verbose. (Verhosity is forced when there is interaction. of course.) This is the<br />

d<strong>et</strong>lUll.<br />

:silent<br />

Don't be verbose.<br />

:noselective<br />

Don't be interactive. just load the patches. The d~',:ault is to query the user on<br />

each patch,<br />

:selective<br />

Query for loading of each patch, This is the default. Note that one may answer<br />

P instead of Y or N to the query: this means proceed. which will cause <strong>al</strong>l<br />

succeeding patches to be loaded non-interactively. load-patches is (supposed to<br />

be) clever to force verbose typeout when it is going to ask. and inhibit it again if<br />

:silent was specified and the loading was proceeded.<br />

The standard l'IL default init file does a<br />

(load-patches :noselective)<br />

to load patches without querying. but verbosely (so that you see what might be taking it<br />

a while during startup).<br />

The fol1owing two functions, if given no arguments, print infonnation about <strong>al</strong>l defined<br />

systems: otherwise, about the systems given as arguments.<br />

pr 1 nt-sys tam-mod 1 f1 cat ions & rest systems<br />

This prints infonnation about the systems as they exist in core. For each system. it lists<br />

its (current) status. and lists the minor version numbers that have been loaded, and their<br />

dcscrip tions.<br />

pr1 nt-systam-h1 story &rest systems<br />

This reads the patch directory for the named systems off of disk. and displays the<br />

infonnation: <strong>al</strong>1 patches and their descriptions are listed (wh<strong>et</strong>her or not they have been<br />

loaded), status changes (the system status may change with a particular minor version<br />

number) are noted, and the "in-core" status with respect to <strong>al</strong>l of this is shown.<br />

Note that <strong>al</strong>though the patch directory is read from disk. the patch system must be<br />

defined in-core in order for this to know where to look for the patch directory.<br />

MC:NII.MAN;PATCH 25<br />

23-DEC-83


Patch System I n formation 282 Nil. Manu<strong>al</strong><br />

26.2 Patch System Information<br />

s1 :system-vers1on-1nfo &option<strong>al</strong> briefp<br />

R<strong>et</strong>urns a string describing .the versions and statuses of the patch systems defined. If<br />

briefp is specified and not nil, then the status infonnation will be abbreviated, some<br />

rinsignificant") systems will not be shown, and the name of the primary system rLisp")<br />

will be omitted (it <strong>al</strong>ways comes ·first).<br />

s1 :g<strong>et</strong>-system-vers1on &option<strong>al</strong> system<br />

R<strong>et</strong>urns multiple v<strong>al</strong>ucs describing the current version of thcspecified patch system:<br />

• the major version number.<br />

• the minor version number,<br />

• and the system status keyword.<br />

By some speci<strong>al</strong> strange dispensation. if system is not defined as a patch system, nil is<br />

r<strong>et</strong>urned as each of the v<strong>al</strong>ues.<br />

s1 :g<strong>et</strong>-system-vers1on-l1st syslem<br />

This is a vestigi<strong>al</strong> r~mnant of Maclisp implementation. Equiv<strong>al</strong>ent to<br />

( m u 1 tip 1 e - v<strong>al</strong> u e - 1 i s t (s i : g<strong>et</strong> - s y s t e In" V e r S ion S)'SI em) )<br />

(In ~1:\n IS£>, the multiple-\'<strong>al</strong>ue support code docs not normany reside in core. and code<br />

which runs interpr<strong>et</strong>ed and needs to examine system version infonnation (for instance<br />

when loading up a system) might not want to force it to be loaded.)<br />

s1! pr1nt.-hAr~1 tt &option<strong>al</strong> 'Otrp(lIn In()Jr.nu!~r:if-t:f)"f'?<br />

This is what prints the startup message. If look-oul-ofcore? is not nil. then si:printher<strong>al</strong>d<br />

reads the patch directories off' of disk so that it can show what the current versions<br />

and statuses are (what you would g<strong>et</strong> if you do load-patches). With a non-null look-oUIof<br />

core? si:prilll-heraid effectively docs a (si:update-system-statuses nil) (q.v.).<br />

s1: update-system-status8s? system-list<br />

Looks on disk and corrects (if necessary) the in-core status information for each of the<br />

systems in system-lisl, or <strong>al</strong>l defined patch systems if that is nil. The reason for this is<br />

that it is possible for the status of a system to change on disk (a particular patch might<br />

be deemed to be broken, or the system might be deemed to be no longer experiment<strong>al</strong>,<br />

for instance). This is done implicitly by load-patches. and by si:print-her<strong>al</strong>d with a<br />

non-null second ar$ument.<br />

26.3 Adding Patches<br />

For th~ fonowing s<strong>et</strong> of functions. a default systcm/minor-version-numbcr pair is maintained.<br />

from which system-name and mil1or-version-number are defaulted. The system name origin<strong>al</strong>ly<br />

defaults to lisp, which is the name of the <strong>NIL</strong> patchable system. (This should be changed.)<br />

s;;add-patch creates a new minor version number, <strong>al</strong>locates it in the patch directory. and s<strong>et</strong>s<br />

this in-core default patch version to that. 111cn one can (for instance) do (si:compile.. loadpatch)<br />

to test that patch. If the function docs not know which minor version numher to de<strong>al</strong><br />

with, then it will cyclc thruugh aU of thcm, from the "most likely" one first. asking. One way to<br />

filrce this behavior is to specify a system but not a minor version number to one of these<br />

functions.<br />

MC:NII.MAN:PATCH 25<br />

2)-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 283 Adding Patches<br />

s 1 : add - pa tch &option<strong>al</strong> system-name descriptiol1 &rest options<br />

This <strong>al</strong>locates a new minor version number for the patchablc system s),slell1-ll<strong>al</strong>llc. with a<br />

description of description and environment options of options (sec the :environmentoptions<br />

keyword to the si:initi<strong>al</strong>ize-patch-system function. on page 285). It then c<strong>al</strong>ls<br />

si:re-edlt-patch. below.<br />

s1: re-ed1 t-patch &option<strong>al</strong> system-name millor-version-number<br />

Creates a patch file for the appropriate file (if necessary). and c<strong>al</strong>ls the built-in editor on<br />

it.<br />

s i : comp 118 - pa tch &option<strong>al</strong> !l),SICI11-IIc1I11C mill"r- version-numbcr<br />

Compiles U1C specified patch. This routine relllrns sever<strong>al</strong> v<strong>al</strong> lies: the first of which is the<br />

path name of U1C compiled file. so that it may he loaded.<br />

s 1 : comp 118-1 oad - pa tch &optionaJ s),stem-name minor-vcrsion-number<br />

Compiles and loads the specified patch.<br />

s 1 : fin 1 s h - pa tch &option<strong>al</strong> system-name mil1or-versioll-llumber<br />

"Compl<strong>et</strong>es" the specified patch: that is. marks it as finished. I f a patch is not<br />

"finished". then load-patches wiJl not load it (nor any succeeding patches).<br />

s 1 : abort - pa tch &option<strong>al</strong> system-name millor-version-number<br />

Flushes (aborts) the specified patch. Any patch files arc not del<strong>et</strong>ed. hO\l,'e\,er: you should<br />

consider doing that manu<strong>al</strong>ly. If the minor version numher was the highest in lise, it wi1l<br />

be rellsed. in which case a later si:add-patch will usc the existing text file to start.<br />

Otherwise, there will be a missing minor version number, which is ok.<br />

s1: s<strong>et</strong>-patch-env1ronment system millor-version-l1umber &rest options<br />

In case you forgot with add-patches. this s<strong>et</strong>s the option environment to opticms. Note<br />

it docs not update the file attribute list in the' source file of the patch ! You must do that<br />

manu<strong>al</strong>ly.<br />

s1: s<strong>et</strong>-system-status system status &option<strong>al</strong> major-version minor-version<br />

Note that "this takes weirder than nonn<strong>al</strong> arguments. This s<strong>et</strong>s the status of the specified<br />

version of system to be status. It is willing to modify the status list of major versions<br />

differing from that defined in the current environment. (Not to say that that would not<br />

be equ<strong>al</strong>ly useful for some of the other functions ... )<br />

The typic<strong>al</strong> use of this is to s<strong>et</strong> either the current or the 0 minor version number of the<br />

current major version of some system to either :released or :broken, with the current<br />

status being :experiment<strong>al</strong> (the default when a new major version number is made). Or.<br />

to change the status of an antiquated system from :released to :obsol<strong>et</strong>e.<br />

MC:NIl.MAN:PATCH 25<br />

23-DEC-83


Defining Patch Systems 284 <strong>NIL</strong> Manu<strong>al</strong><br />

26.4 Defining Patch Systems<br />

s1: new-patch-system system-name pat/moille &option<strong>al</strong> (do-what :increment-<strong>al</strong>ld-define)<br />

s1: 1n1t1<strong>al</strong>1ze-patch-system system-name p<strong>al</strong>hllame &key :initi<strong>al</strong>-version<br />

:patch - directory :patch - file :compilation - function :editing - function<br />

:insignificant :default-directory :default-device :nodefault<br />

:environment-options<br />

:nodefautt<br />

If not nil. then si:initi<strong>al</strong>ize-patch-system will read in an eXlsttng version of the<br />

patch system definition file from pelflmam (appropriately dd:lllltcu) (0 provide<br />

de~lllils for those options not specified. Otherwise. hopefully appropriate default<br />

defaults arc used.<br />

:initi<strong>al</strong>-version<br />

May be used to specify the version to he uscd. Thiswitl be written into the<br />

patch system definition file as the CUrrl'1I1 version. which means that c<strong>al</strong>ling<br />

si:new-patch-system with the (typiccdl) :increment-and-define keyword will<br />

increment it first.<br />

:patch -directory<br />

A fonnat string which should take one argument. which is . the major system<br />

version. to construct the patch directory pathnamc for that major system version.<br />

·n~tr.h -fil~<br />

r·· -<br />

A format string which should take two arguments. the major and minor system<br />

versions (in tllat order). to construct the patch file patllname for thepatchs of<br />

those versions. Alternately. it may be a list of two such fonnat strings: the first<br />

will be used as the source file pathname. the second for the \'asl fiJ~. (This may<br />

be used to split the stuff across directories or even structures, for instance if the<br />

sources are kept in a different place because of lack of disk space. or are simply<br />

not kept somewhere on some particular machine.)<br />

:compi lation - function<br />

The function caUedby compile-patch <strong>et</strong>c. By default compile-file (page 244) is<br />

used. This should be a. symbol. not a closure or compiled-function object. The<br />

function wiH be given a first argument of the input pathname. and other<br />

kcyworded argumenl~<br />

of :output-file and :s<strong>et</strong>-default-pathname (which will be<br />

nil so as to not modify pathname defaultS). That is,<br />

( 1 sbe 1 illpul-parhname<br />

: output-fi 1 e output-pathname<br />

:s<strong>et</strong>-default-pathname nil)<br />

:editing- function<br />

The editing function which should be used to edit a patch file. It is c<strong>al</strong>1ed with a<br />

single argument. the patch file path name. The default function simply r<strong>et</strong>urns the<br />

list of "now" "edit" and the pathname 9 which is then r<strong>et</strong>urned by si:add-patch<br />

or si:re-edit-patch.<br />

:insignificant<br />

If not nil. then si:system-version-info will not show this system when in brief<br />

MC:NII.MAN:PATCH 25<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong><br />

285 I )cflning Patch Systems<br />

mode.<br />

:default-directory<br />

:default-device<br />

These are used to construct the default pathnames used for the :patch-directory<br />

and :patch-file options, when they are not supplied. They are 1101 used in<br />

defaulting (<strong>al</strong>though they probably should be). The default-defaults for these are<br />

taken from p<strong>al</strong>hllame. and if absent from that. the directory name defaults to<br />

system-name. These options are significantly less useful in 'II. than they were in<br />

the ~1ACI .IS}> version of this code ...<br />

:environ ment - options<br />

This and some of the code involved is parti<strong>al</strong>ly but not tot<strong>al</strong>ly archaic: it predates<br />

:\11. file attrihute lists. and was put in to compensate for their ahsence. The code<br />

in Release 0 still performs redundant bindings of the in\ohed attributes.<br />

However. the data in this option list is used to <strong>al</strong>so initi<strong>al</strong>ize the textu<strong>al</strong> file<br />

property list when si:add-patch initi<strong>al</strong>izes the 'patch file. Because of the<br />

kludginess of this. only a few options are supported. <strong>al</strong>though it is extensible if<br />

need be (see the code). The options currently handled are<br />

:package<br />

The package name (default is "SYSTEM-INTERNALS", which is probably<br />

a poor choice)<br />

:input-radix<br />

The input iadix (default i5 dedman.<br />

LSB, which has been distributed with <strong>NIL</strong>, is a patchablc system <strong>al</strong>so. However, the nonn<strong>al</strong><br />

~IL environment does not have LSB loaded by default. There is a file which can be loaded which<br />

wi1110ad up <strong>al</strong>l of the parts of LSB. (It is <strong>NIL</strong>$DISK:[LSB]LOAD.LSP. if you have ISB online.)<br />

Esscnti<strong>al</strong>ly, it s<strong>et</strong>s up the Isb package and loads up <strong>al</strong>l of the component files of lSB and<br />

performs whatever initi<strong>al</strong>izations are needed, and then does<br />

(si:new-patch-system<br />

"LSB" "<strong>NIL</strong>$DISK:[LSB.PATCH]SYSOEF"<br />

:define)<br />

(load-patches :noselective)<br />

The file N 1 L$D ISK : [LSB . PATCH ]SYSDE F • PSD was created with the si:initi<strong>al</strong>ize-patch-system<br />

function. Once that has been created, this refcrence to it in the ISB loadup file is the only<br />

pathname reference necessary; <strong>al</strong>l others are contained in that file.<br />

With the LSB patchable system, the files which are loaded by the loadup file are not nonn<strong>al</strong>ly<br />

modified except via patches. However, at strategic points. like when many files are being changed<br />

at once, or incompatible changes are being made. or the patches become numerous. then <strong>al</strong>l of<br />

the files are changed (for instance, recompiled) at once, and the maintainer manu<strong>al</strong>ly increments<br />

the version number of the LSD patchable system by doing<br />

(si:new-patch-system 'lsb "nil$disk:[lsb.patch]sysdef"<br />

:increment)<br />

which increments the on-disk version number. Then. when someone loads the loadllp file. they<br />

g<strong>et</strong> the new files. the new major version number, and (until new patches gel made) no patches<br />

loaded.<br />

MC:NII.MAN:PATC1-I25<br />

23-DEC-83


Defining Patch Systems 286<br />

M~intaining the system in this way <strong>al</strong>so result'i in a shorter turnaround time for testing out<br />

sm<strong>al</strong>l fixes. and g<strong>et</strong>ting them "inst<strong>al</strong>led"; larger source files do not need to be rccompiled.<br />

~lC:~II.~1AN:PATCH 25<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 287 T<strong>al</strong>king to <strong>NIL</strong><br />

27. T<strong>al</strong>king to <strong>NIL</strong><br />

27.1 Startup<br />

'Inc first thing ~IL docs when it starts up is to attempt to figure out what kind of tennin<strong>al</strong><br />

you arc using. The way <strong>NIL</strong> figures out how to t<strong>al</strong>k to a particular tennin<strong>al</strong> is that it uses<br />

"tennin<strong>al</strong> capahilities" database (a C~IX lenncap database). "Ibe VMS logic<strong>al</strong> name term is used to<br />

name the tennin<strong>al</strong> type: ~II ignores VMS tenninaI infonnation. If no such logic<strong>al</strong> name is<br />

defined. then ~Il will assume tJle tenninaI is a simpleminded printing termin<strong>al</strong>. and prompt you<br />

for a tcnninaI name.<br />

The termin<strong>al</strong> names which arc both supported and known to work fairly wen arc<br />

vt52<br />

Standard DEC VTS2.<br />

c100<br />

Human De~:gned System's concept-"IOO. This will probably work for their Concept-l08<br />

<strong>al</strong>so.<br />

aaa<br />

Ann Arbor Ambassador<br />

vt100<br />

DlT vt100. Obviously you should make sure your vt100 is in ANSI mode. Also. autolinewrap<br />

should be disabled.<br />

In OCL. one m igh t say<br />

$ define term "cIOO"<br />

if one was on a concept-H)(). Or. if your tennin<strong>al</strong> varied. you might put in your log in. c om file<br />

$ inquir term "Termin<strong>al</strong> type (in doublequotes. default vt52)"<br />

$ if term _eqs. "" then term := "vt52"<br />

$ define term "-'term'"<br />

which would prompt for the tennina] type to assign to the term logic<strong>al</strong> name, defaulting it to<br />

whatever was convenient.<br />

When <strong>NIL</strong> starts up, it loads your illit file if it exists. This would be a file on your login (not<br />

default) directory named <strong>NIL</strong> ~ I N I. (lnit file conventions are discussed on page 200.) Then it<br />

enters its standard read-ev<strong>al</strong>-print loop.<br />

~1C:NII.M;\N:TAI.K 16<br />

23-DEC-83


"I'hc Toplevcl J .(lOP 288 <strong>NIL</strong> Manu<strong>al</strong><br />

27.2 The Toplevel Loop<br />

•<br />

••<br />

•••<br />

Variable<br />

The v<strong>al</strong>ue of this is the last thing the top)cvel (or brcakJevcl) loop ev<strong>al</strong>uated (and<br />

presumably printcd).<br />

The previous v<strong>al</strong>ue of •.<br />

The previolls "<strong>al</strong>ue of ••.<br />

Variable<br />

Variable<br />

+<br />

Variable<br />

The \'<strong>al</strong>ue of this is the last thing rcad in by the top)evcl (ur breakleve1) loop.<br />

++<br />

+++<br />

Previous v<strong>al</strong>ues.<br />

Variable<br />

Variable<br />

\\<br />

Variable<br />

This has as its v<strong>al</strong>ue the lteClor of v<strong>al</strong>ues r<strong>et</strong>urned from the last thing ev<strong>al</strong>uated' by the<br />

toplc\ cl (or brcaklcyel) loop. That is. its first (number 0) e)cment will be the v<strong>al</strong>ue of •.<br />

This variable is <strong>al</strong>so used by the dcbuggcr the way • is by the toplcvel loop. but that<br />

will bc changcd eventu<strong>al</strong>ly.<br />

If an ev<strong>al</strong>uation error occurs and you abon back to toplevcl, then the v<strong>al</strong>uc of the • variables<br />

docs not g<strong>et</strong> cycled. but the + variables do: thus. + is the fonn which got the error, but • is<br />

still the last thing r<strong>et</strong>urned by toplcycl ev<strong>al</strong>uation. C0\1\10\ LISP intends to change this. (What<br />

<strong>NIL</strong> docs is compatible with MACLISP.)<br />

27.3 Entering and Exiting <strong>NIL</strong><br />

Typing the character control-Y norm<strong>al</strong>ly exits from NIl. The same command which started<br />

the <strong>NIL</strong> initi<strong>al</strong>ly may then be used to resume it. The <strong>NIL</strong> can be resumed in other ways too. For<br />

instance, if nil was thc command used to stan the nil,<br />

nil<br />

will resume the existing NJL,<br />

nil/kill<br />

will kill the <strong>NIL</strong>, and<br />

n i 11 pro c e e d will resume the <strong>NIL</strong>, but not <strong>al</strong>low it to type out. and will leave you in the<br />

command interpr<strong>et</strong>er. If the Nil. attempts to type out (or. in fact, c<strong>al</strong>ls any of<br />

the following functions). it will wait until it is explicitly resumed.<br />

If SIL is reading input from the tennin<strong>al</strong>, the input processor command for "m<strong>et</strong>a"<strong>al</strong>unode'"<br />

which may be typed as the character sequcncc CUllIro!- \ a!/mode, will r<strong>et</strong>urn control to the<br />

command interpr<strong>et</strong>er. When the <strong>NIL</strong> is resumed. it will automatic<strong>al</strong>ly redisplay the typein it is<br />

accumulating.<br />

MC:NII.MAN:TALK 16<br />

23-DEC-83


-., il"AIIl'ii!il':!I' '. '~-~--' -' 7r' '''r ,'" ' :"°11' E'"<br />

N II. Manu<strong>al</strong> 289 Entering and Exiting <strong>NIL</strong><br />

Sc\'e'r<strong>al</strong> functions are provided for r<strong>et</strong>urning from Nil to the \'\1S command language<br />

interpr<strong>et</strong>er (ell) in a more programmable fashion. In <strong>al</strong>l of the t()lIowing functions where a string<br />

is involved with passing control back to the cu. the string may have a maximum length of 256<br />

characters. This is checked for by <strong>NIL</strong><br />

v<strong>al</strong> r<strong>et</strong> &option<strong>al</strong> command-line<br />

(v<strong>al</strong>r<strong>et</strong>) r<strong>et</strong>urns control to the CLI. The <strong>NIL</strong> is suspended until later resumed.<br />

(v<strong>al</strong> r<strong>et</strong> cOll1l11tllJti-lin(') r<strong>et</strong>urns to the n.I (suspending the ~II,).<br />

comm<strong>al</strong>ld-lin(' to be interpr<strong>et</strong>ed as a command line by the CI.J.<br />

and addition<strong>al</strong>ly causes<br />

quit<br />

The passlIlI termin<strong>al</strong> mode is cleared, and restored when the 'II is reslImed.<br />

a string ~lrglll1lcnt works hy c<strong>al</strong>ling the \'\tS lib$do_command library routine.<br />

(quit) exits the <strong>NIL</strong>, causing it to be killed.<br />

v<strong>al</strong>r<strong>et</strong> with<br />

Currently. (quit SIring) kiHs the !\Ii. and causes Siring to be printed instead of "N II.<br />

Terminated": howe\ er this will probably be changed so that SIring will be interpr<strong>et</strong>ed (IS a<br />

command line. as with v<strong>al</strong>r<strong>et</strong>.<br />

Pass<strong>al</strong>l mode is cleared on exit.<br />

\\'hen the ~II. is terminated. there is a noticeable pause before the command language<br />

interpr<strong>et</strong>er r<strong>et</strong>urns. This is due to the controlling program (R'II.. nlllning in the ell)<br />

waiting t()r the process to actu<strong>al</strong>ly go away. V\fS image rundown wkes a noticeable time.<br />

and if one were to not wait after requesting process del<strong>et</strong>ion. starting up a <strong>NIL</strong> of the<br />

same name immediately could cause the new R~IL to be confused. (This is the same as<br />

happens when nil/I< i 11 is used in the cu.)<br />

ex 1 t - and - run - program (pathname)<br />

Control is r<strong>et</strong>urned from <strong>NIL</strong> to the CLI. and the program image found in pathname is<br />

then run. The l'IL will have been suspended. ~IL applies no defaulting to pathname,<br />

however. the command interpr<strong>et</strong>er will supply a default file type of exe and will default<br />

the device and directory to the RMS default<br />

PassaJl mode is cleared on exit. eXit-and-run-program works by having the R<strong>NIL</strong><br />

program caIl the lib$run_program library routine.<br />

proceed-nil &option<strong>al</strong> SIring<br />

Control is r<strong>et</strong>urned from the <strong>NIL</strong> to the CLI. However. the <strong>NIL</strong> is resumed. so will<br />

continue running "without the tennin<strong>al</strong>". If a SIring is supplied, then that is printed (as<br />

with quit). Similarly (as· with quit). the interpr<strong>et</strong>ation of Siring should probably be<br />

changed to be a command line for the eLI to execute.<br />

MC:NII.MAN:TALK 16<br />

23-DEC-83


VMS 290 Nil. Manu<strong>al</strong><br />

27.4 VMS<br />

VMS usurps control-Y as interrupt-to-superior. Resuming your <strong>NIL</strong> gives it a tty-r<strong>et</strong>urn<br />

interrupt which makes it frob the cursor so that it knows where the cursor is. (This is why it<br />

goes to the bottom of the screen on a display tty.)<br />

Other tennin<strong>al</strong> intermpts are aU perfonned by dispatching from c(}ntrol-C~ after the control-C<br />

is typed another character is read. ("?" lists options.) The contro]-C processing is perfunncd by<br />

l.isp code. This means that control-C win not be processed if interrllpt~ arc severc1yinhibited.<br />

The ~II system hy speci<strong>al</strong> dispensation will enter the VMS debugger if multiple control.;Cs are<br />

typed and arc hC'ing ignored: so if som<strong>et</strong>hing large and uninterruptih1c is happening. like creating<br />

it veClOr with a mjllion clements. or som<strong>et</strong>hing not so large but your system is slow. you might<br />

throw the :"11 out to the V\IS debugger.<br />

It is highly unlikely that Nil. will enter the V~fS debugger unless explicitly told to do so.<br />

Here arc two \,\15 debugger commands that are useful for r<strong>et</strong>urning back to the wurld. Say<br />

c<strong>al</strong>l debug .<br />

and the lisp dehugger will be entered. (Exiting $oftly from the Lisp dcbug;:i:·'r with "q••<br />

will<br />

r<strong>et</strong>urn to the \'\IS debugger. One may <strong>al</strong>so perfonn a non-loc<strong>al</strong> exit from the l.isp debugger with<br />

control-G or X.) One can <strong>al</strong>so just<br />

c<strong>al</strong>l quit<br />

frum the V~fS· debugger. which docs a throw just like contro)-G docs from the control-C prompt.<br />

'.11(\ only prnhll'm witl1 ~H thi~ is. tJ,:lt ifth~ 'A1S d~bugg~r g<strong>et</strong>s dynamka1!y laadt'd inta t'1c<br />

11\11. some part of it will end up where ~IL thinks it is putting its heap (Le.. where it is anocating<br />

the memory to use for consing). and U1C ~Il.. will die shortly thereafter.<br />

s1:11sp-debugger-on-except1ons<br />

Vanabk<br />

If non-null, then error conditions and faults will trap to the LISP error handler rather than<br />

bombing out to the \~S debugger. This can happen from memory access violation errors,<br />

floating overflow and underflow, integer divide by zero, ctc.; in gener<strong>al</strong>, any such error.<br />

For instance, a reserved operand fault might occur if a variable-field byte instruction was<br />

given a bad size.<br />

If the lisp debugger is used from some exception<strong>al</strong> condition, remember that the stack may<br />

not be in a nice-looking state, so examination of what the debugger thinks are loc<strong>al</strong> variables near<br />

the top may resull in more trouble. Note <strong>al</strong>so that the Lisp code is not run at AST level, but<br />

rather as a continuation of the condition: r<strong>et</strong>urning a v<strong>al</strong>ue from the debugger r<strong>et</strong>urns that v<strong>al</strong>ue<br />

from the most recent VAX procedure c<strong>al</strong>l, which is probably the function within which the error<br />

was sign<strong>al</strong>led. Also. the USP code which handles such errors binds si:lisp-debugger-on"<br />

exceptions to nil when it is running: examination of non·USP data by the debugger from such<br />

an error as if it were usp data might cause a memory protection violation, and blowout to the<br />

VMS debugger.<br />

Note <strong>al</strong>so the s<strong>et</strong>-privileges and g<strong>et</strong>-privileges functions (page 233). which can be used to<br />

s<strong>et</strong> or g<strong>et</strong> the privileges the 1"11. process has enahled.<br />

~lC:<strong>NIL</strong>M"N:T"LK 16<br />

23-I)FC-83


N II. Manu<strong>al</strong> 291<br />

I nSl41llation<br />

27.5 Inst<strong>al</strong>hltion<br />

There are 4 parts to inst<strong>al</strong>ling VAX - <strong>NIL</strong> at your site.<br />

J<br />

Restoration of the nil directory hierarchy from the backup tape.<br />

2 Definition of the required logic<strong>al</strong> names and symbols.<br />

3 Invoking the LISP dynamic Iinkcr.<br />

4 Handling System and User considerati


I nsutllation 292<br />

<strong>NIL</strong> Mctllu<strong>al</strong><br />

example: To go from \,~1S 3.0 to VMS 3.4 you may have to do the following:<br />

$ BLISS/LIB <strong>NIL</strong>LIB:NIlLIB<br />

$ SET OEF [NIl.FOO]<br />

$ BLISS RNIl<br />

$ @R<strong>NIL</strong>LINK<br />

$ NLINK<br />

$ LISPLINK<br />

[Step 4)<br />

See the file <strong>NIL</strong>$OISK:[<strong>NIL</strong>.COM]<strong>NIL</strong>INSTAL.COM. which can be mo,'ed (perhaps edited first)<br />

to SY$$MANAGE R. Then add this to SYSTARTUP. COM: .<br />

$@SYS$MANAGER:<strong>NIL</strong>INSTAl<br />

Then lIsers who \\ ~lIll to usc \11 must h~lve executed in their login files:<br />

$@<strong>NIL</strong>$DISK:[<strong>NIL</strong>.COM]USYMS<br />

This will s<strong>et</strong> up the the standard way of c<strong>al</strong>ling Nil .•<br />

$ <strong>NIL</strong><br />

Which will run r\JL as a subprocess. 'tV or (v<strong>al</strong>r<strong>et</strong>) will exit the subprocess: to resume, type:<br />

$ <strong>NIL</strong><br />

or to kill the subprocess:<br />

$ <strong>NIL</strong>/KILL ! from OCl<br />

(QUIT)<br />

from IISP<br />

The directory [<strong>NIL</strong>.SITE1 has two files of interest: [<strong>NIL</strong>.SITE]SITEPARAMS which jf it exists<br />

in compiled fonn will be loaded right before the LISPLINK saves thcvinu<strong>al</strong> memory image.<br />

And [NII..SITEjDEFAULTJNI. which is loaded at "re-startup" time if the user docs not have a<br />

SYS$I.OGIN:<strong>NIL</strong>INI file. After N1L is created on your system then you should edit<br />

SITEPARAMS and compile it. The information is noncritic<strong>al</strong> however.<br />

Upon startup <strong>NIL</strong> will look for the logic<strong>al</strong>-name ftTERM" to d<strong>et</strong>cnnine the type of termin<strong>al</strong> it<br />

is connected to. For example:<br />

$ Define TERM "vt100"<br />

Presently it docs an its own cursor positioning using the data in the file <strong>NIL</strong>STERMCAP. If the<br />

logic<strong>al</strong> name "TERM" is not defined then <strong>NIL</strong> will prompt the user for the info upon stanup.<br />

[Option<strong>al</strong> Verification 1<br />

In <strong>NIL</strong> do:<br />

(LOAD "NIlSDISK:[NIl.VERIFY)VERIFY")<br />

(VERIFY "TEST")<br />

Then sit back and watch the little demonstration. No. we do not have program verification<br />

technology to the point where this gives a proof of correctness for the <strong>NIL</strong>. However ... , then run<br />

$ DIFFERENCES NIlSOISK:[<strong>NIL</strong>.VERIFY]TEST.LIS<br />

(What if FaiJure?j<br />

If you ran out of disk space in step 1, then we can suggest that you somehow make more space<br />

temporarily. (e.g. backup and del<strong>et</strong>e fites), and then prune down to the minimum given in<br />

NII.S])ISK:(<strong>NIL</strong>.PORT]MINIPORT.COM when step 3 is compl<strong>et</strong>ed.<br />

MC:<strong>NIL</strong>MAN~T;\I.K 16<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 293 How the Nil. Control Works<br />

Step 2 couldn't fail. as <strong>al</strong>l it does is define logic<strong>al</strong> names and symbols.<br />

Step 3 could fail if various system generation param<strong>et</strong>ers and account quotas are not s<strong>et</strong> high<br />

enough. Many sites will fail here, as the default VIRTUALPAGECNT of 8 thousand pages is not<br />

sufficient. (Although it is sufficient to do LX B<strong>NIL</strong> which does not load the compiler): 16<br />

thousand pages is enough to g<strong>et</strong> started in lisp programming. Other things to look out for are<br />

insufficient pagefi1c and per-account pagefile quota.<br />

Default account param<strong>et</strong>ers as supplied by DEC have found to be sufficient under VMS 3.0.<br />

but some sites have been found to severly restrict param<strong>et</strong>ers. which has proved to be extremely<br />

frustrating. at that suhs<strong>et</strong> of those sites where the loc<strong>al</strong> expertise for debugging prohlems caused by<br />

Stich restrictions is insufficient.<br />

It is possihle to nll1 <strong>NIL</strong> on a V AX-11/750 with a single RK07 disk. (a mere 27 megabytes!)<br />

as we do here at MIT. However. it is not possihle to link a <strong>NIL</strong> on such a tig.ht system. Ide<strong>al</strong><br />

system environments have been found on sites config.ured to rlln large databases efficiently.<br />

In step 4. note that the running <strong>NIL</strong> image is mostly pure. sharable. code and data, so there<br />

is a big performance payotf in proper insWllation and SYSG EN tuning on a multi-<strong>NIL</strong> -user<br />

system. If LISPl.lNK works. but <strong>NIL</strong> docs not, then it may be due to insufficient glob<strong>al</strong> sections<br />

and pages.<br />

rOther Options]<br />

If vou want to be able to use the VMS debugger on the nmning lisp imrlgf' rhf'n ('1(C'('ut(' th('<br />

following:<br />

$RUN [<strong>NIL</strong>.HACKS]SETDEBUG<br />

Giving <strong>NIL</strong>$DISK:[<strong>NIL</strong>.EXF]LISP.EXE: as the filename, and answering Y to the question. With<br />

this s<strong>et</strong>ting <strong>NIL</strong> will start up in the VMS debugger. and you must type GO(CR) to actu<strong>al</strong>ly start<br />

it.<br />

27.6 How the <strong>NIL</strong> Control Works<br />

This section notes how some of the above stuff works, for the interest of VMS haCKers, or<br />

those wishing to extend the above function<strong>al</strong>ity.<br />

Program control of <strong>NIL</strong> under VMS works in a fairly strang~ way (or at least so it will appear<br />

to someone used to operating systems in which there is more explicit job/termin<strong>al</strong> association and<br />

more "monitor" control of inferior processes). This is a function of VMSS lack of a concept of a<br />

job "having control of the termin<strong>al</strong>", and the fact that the N1L process does not contain a<br />

command language interpr<strong>et</strong>er in its image: the spawn and at tach commands are only<br />

implemented by conventions applied by the CLI.<br />

The command nil typic<strong>al</strong>ly invokes the R<strong>NIL</strong> program. This is an image which runs within<br />

the CI I process, and "controls" the !'Il., which is kept in a separate process. The nil command<br />

implicitly supplies lots of arguments to R<strong>NIL</strong>. one of which is the job name of the <strong>NIL</strong> process.<br />

R'II ~ ill create one if there is none, or will do som<strong>et</strong>hing else to it (like resuming it) depending<br />

on addition<strong>al</strong> arguments given (like ni l/proceed or ni 11k ill). RNll communicates to the<br />

<strong>NIL</strong> process with mailboxes. When the ~Il is resumed. the RNll. attempts to read from one,<br />

MC:<strong>NIL</strong>MAN:TALK 16<br />

23-DEC-83


How the <strong>NIL</strong> Control Works 294 <strong>NIL</strong> Manu<strong>al</strong><br />

w<strong>al</strong>ling. It r<strong>et</strong>urns either when it succeeds in reading a mesSt1ge (as happens with v<strong>al</strong>r<strong>et</strong>). or if it<br />

is abnorm<strong>al</strong>ly exited (41S with typing contro)-V).<br />

VMS in its current state does not have the concept of a particular process having "contro'" of<br />

the termin<strong>al</strong> it shares with the rest of the process trec. <strong>NIL</strong> handles this by having a number of<br />

event and st<strong>al</strong>e flags which ten it wh<strong>et</strong>her or not it is <strong>al</strong>lowed to read from or write to the<br />

tennin<strong>al</strong>. When a Nil. is exited. the R~II. program clears those flags: when it is resumed. they<br />

arc turned back on again.<br />

Exiting from ~II with contfol-Y works in a particularly strange fashion. The VMS (ennin<strong>al</strong><br />

dri\er will give it control- Y AST (0 any process whi(:h has enahled it with no conceptu<strong>al</strong>ization<br />

of what program is "in comrol or the tennin<strong>al</strong>. The control-Y is handled by the CI.I. which<br />

then commences image nmdown of the R~IJ. program. R~1I has (In exit handler which then s<strong>et</strong>s<br />

the tenllinaI input and output enabled flags off in the!':11 process. (As a speci<strong>al</strong> case. it may <strong>al</strong>so<br />

exit similarly if the ~II. is terminated somc other way. perhaps by ex it to the "'1S debugger in<br />

thc <strong>NIL</strong> process. It recognizes the mailbox message for this. and prints "<strong>NIL</strong> Terminated".)<br />

'<br />

Control-C has a similar control problem. When a controJ-C is typed on the termina1. the<br />

termin<strong>al</strong> drivcr nms t11C AS.,. routincs for <strong>al</strong>l processes which have enahled thclll. (Multiply. if a<br />

process has cnah1cd more than one.) In the current implementation. thc ~II. process en~lhJes the<br />

conlrol-C AST. \Vhen the AST routine is run. it attempts to d<strong>et</strong>ennine if it should be the<br />

rccipicl1l of that interrupt. by checking to see if it "has control of the tennin<strong>al</strong>" (i.e.. the<br />

terminaHnput-enabled flag is on), If not. it ignores the intermpt (and of course fe-enables the<br />

rlln"'l\l.r 'H::'\<br />

_ ............ ~ • .... _ ..".,_ Ifit thin"&:-<br />

••• ~ _ ................<br />

it U'"lC'<br />

""..# th,. ..,.""n'"'''' .... f ,I.. "<br />

....................,.-...... •." w.'" ;... ,,,......_t of<br />

a.&,,~ •• t. • .., .... ,-. ""'''-t.l''''''''.' "..........,..1.. th,.. .... "" ,..,..n, ...." •• .."I.r I." 1-0,..1-...<br />

"L.v. '- , ... v , ......,<br />

keep other <strong>NIL</strong>s on Lhe same temlin<strong>al</strong> from having to think about it. i guess), and queues a LISP<br />

interrupt for control-C. There is one time when t11is can break down: if the ~ILis suspended<br />

when the AST is delivered. the AST wiJI not be run until the r\1l. is resumed. However. when<br />

the Nil. is resumed. the R:'\Il. delivers ita couple other ASTs which cause the tennina) input and<br />

output flags to be turned on! If this manages to happen before -the control-C AST routine g<strong>et</strong>s<br />

around to checking thesc flags (as it invariably docs). then the SIL will think that this control-C<br />

was for it, and behave accordingly. So, if you resume a <strong>NIL</strong> and it acts likc you just typed a<br />

control-C, it is probably because of that control-C you typed at the d i sp 1 ay program h<strong>al</strong>f an<br />

hour ago; type "n" at the n>Interrupt)'· prompt to make it go away.<br />

There is a design change which eliminates this problem. and addition<strong>al</strong>1y <strong>al</strong>lows controlled<br />

interruptibiHty out of arbitrary wait operations (not just tcnnin<strong>al</strong> input and output, which are<br />

speci<strong>al</strong> cased). It involves a sweeping change to lots of code. however. so cannot be put in bits<br />

at a time.<br />

MC:<strong>NIL</strong>MAN;TAJ.K 16<br />

23-I)EC-83


Ofirjrnttxd't<br />

N II. Manu<strong>al</strong> 295' Peripher<strong>al</strong> Utilities<br />

28. Peripher<strong>al</strong> Utilities<br />

This chapter will accumulate documentation on various minor utilities which are distributed<br />

with I'lL. but which are not necessarily part of <strong>NIL</strong> proper.<br />

28.1 The Predicate Simplifier<br />

Nil offers a predicate simplifier. which simplifies l.lsp-format predicates into disjunctive nonn<strong>al</strong><br />

t{lfI11. This progr,lm was origin<strong>al</strong>ly written hy I )eepak Kapur with thc help of Ramcsh Patil for<br />

th~ PRO'I OSYS 1"'\1 'llItomatic programming project directed h) \Villi4lm Martin at ~v11T in the mid<br />

1lJ70s. Since then. it has heen convened to lise ISH [4]. hrought lip in both liSP \1:\CIII:\F liSP<br />

and '11. and imprm ed at a low levcl. The code for this is not loaded hy dcf~Hl1t in '": it<br />

exists as nil$disk:[nil.utilities]simp. and to load it. the package definition file<br />

nil$disk:[nil.utilities]simp.pkg should he loaded first. This may he perflmned<br />

automatic<strong>al</strong>ly by use of<br />

( r e qui r e 's imp)<br />

See require. page 123.<br />

This simplifier only re<strong>al</strong>ly works on simple predicatcs and connectives. It perfonns some<br />

trivi<strong>al</strong> canonic<strong>al</strong>izations of arithm<strong>et</strong>ic operations and inequ<strong>al</strong>ities (equ<strong>al</strong>. greaterp. and lessp), but<br />

it does not truly recognize identities or other relations among them. There is <strong>al</strong>so a read-time<br />

(compile-time) condition<strong>al</strong>ization for wh<strong>et</strong>her it attempts to de<strong>al</strong> with existenti<strong>al</strong> quantification. as<br />

r('nr('c('''tt.,.t<br />

·-r·--- ..··_- h"<br />

......<br />

f"rnlC Ilf th,.. ft,\rnl<br />

J ."'..................- " ..."." ••<br />

(for-some (kl k2 ... kll) pred)<br />

This feature is nonn<strong>al</strong>ly turned off, which simplifies the intern<strong>al</strong> dawstructures used and improves<br />

the efficiency in the other cases. Again, simplification of fonns containing existcnti<strong>al</strong> quantification<br />

does not <strong>al</strong>ways reduce as well as it should. To g<strong>et</strong> this one would have to recompile simp with<br />

that feature turned on.<br />

simp pred-fonn<br />

Simplifies prcd-fonn. For example.<br />

(simp '(and c d (or a b») =><br />

(or (and a c d) (and bed»<br />

s1mpor pI p2<br />

s impand pi p2<br />

Approximately equiv<strong>al</strong>ent to<br />

(s imp (1 is t and-or-or pI p2»<br />

s 1mpnot pred<br />

Simplifies the not of pred.<br />

simp 0 r 11 s t pred-Iist<br />

S 1mpandl1 s t pred-list<br />

Simplifies the or or and of pred-list.<br />

MC:<strong>NIL</strong>MAN;UTILS 15<br />

23-DEC-83


\ Mini-MYCIN<br />

296 N II. Manu<strong>al</strong><br />

.s 1mpor pi p2<br />

.s 1mpand 1'1 pl<br />

pI and p2 must <strong>al</strong>ready be in disjunctive nonna} fonn. i.e .• <strong>al</strong>ready simplified (as r<strong>et</strong>urned<br />

by some simplification c<strong>al</strong>l). l'bisis faster than using simpor or simpand .<br />

• s impor 11 s t pred-list<br />

.$ impandl i st pred-list<br />

Simplifics thc or or and of the predicates in pred-list. which must be <strong>al</strong>ready simplified .<br />

• s 1mpnot pred<br />

Simplifies the not of pre(/. which must be ah'c41dy simplificd.<br />

There is <strong>al</strong>so a hack for doing both uniqui1.ing of predic411es r<strong>et</strong>urned. and <strong>al</strong>so "atomizing".<br />

associating an atomic symbol with a predicate (which will be expanded out in subsequent<br />

simplification). The fonner was important in the PIW-I0 ~ACI.ISP version when large databases<br />

associating predicates with probabilities were in use. See the source code if either of thesc are<br />

desircd.<br />

28.2 A l\1ini-MYCIN<br />

'Ibis is a sm<strong>al</strong>l production rule systcm upon which class projects in the MIT course 6.871<br />

were implcmentcd. Some students in the course ulught this tenn by Prof. P<strong>et</strong>er Szolovits and Dr.<br />

Ramesh PatiJ used this code in <strong>NIL</strong>. The directory <strong>NIL</strong>SOISK: [MYCIN] has what the students<br />

gut to st


<strong>NIL</strong> Manu<strong>al</strong> 297 Maclisp Compatihilil) for Macsyma<br />

28.3 1\1aclisp Compatibility for Macsyma<br />

The directory NI L$OISK: [MACSYMA] has some code in that is used for compiling and<br />

running MACSYMA in <strong>NIL</strong> and that will be useful to anyone porting a MACLISP program.<br />

The file ALOAO. LSP has an autoloading handler that works by handling the :undefinedfunction<br />

error condition. This might be a gener<strong>al</strong>ly useful thing to have around.<br />

The file PKGMC. LSP illustrates the usc or. pkg-create-package and intern-loc<strong>al</strong> in order to<br />

build a namespace that shadows conflicting or incompatibly defined functions and variahles.<br />

The file N I LCOM. LSP gives definitions of the functions map. subst. member. and assoc,<br />

which are compatible with \1 ACI.JSP.<br />

MC:<strong>NIL</strong>MAN:UTILS 15<br />

23-DEC-83


Foreign Language Interface 298 <strong>NIL</strong> Manu<strong>al</strong><br />

29. Foreign Language Interface<br />

29.1 Introduction<br />

It is desireable to be able to can from <strong>NIL</strong> procedures that are written in other VMS<br />

supported languages. such as FORTRAN, COBOL. PLI. Buss. C. PASCAL. Ian {Basic}. <strong>et</strong>. a1.. not<br />

to mention procedures written in MACR032. and VMS library routines and system services.<br />

Fortunately this is easy. due to the the uniform VMS object and symhol table file format.<br />

uniform procedure c<strong>al</strong>l mechanism. and rich s<strong>et</strong> of 1'\11. datMypes from which to construct<br />

d41tastructures compatible with what various fhreign language routines expect to receive.<br />

The presently implemented interface is by no means the last word in sllch endevors: for<br />

example it makes no <strong>al</strong>lempt to enforce datatype restrictions in argument passing: however. it is<br />

t(lUlH.l to be function<strong>al</strong>. and is used in the ~II. system ibc1f to access some VMS system services.<br />

to increment<strong>al</strong>y debug parl~ of the assembly-language kerna1. and to interface to "numbercrunching"<br />

f'C.·'TRAN subroutines and to some users .existing C libraries.<br />

29.2 Kernel and System-Services<br />

The executable code for such procedures is <strong>al</strong>ready in the lisp process address space. therefore<br />

accessing them is only a matter of defining an argument-data-convention interface. searching the<br />

lisp or system symbol table to g<strong>et</strong> the required machine address. and creating a lisp subr<br />

tr'lmpoline. similar to an element of a transfer vectors the VMS linker would create when one<br />

references sharable libraries.<br />

s 1 : defsysca 11 (lisp-name vms-symbol) &rest arguments pees<br />

Does everything needed to reference a routine in "LISP.STU" or "SYS.STBtt. The lispname<br />

is defined as a speci<strong>al</strong>-form taking <strong>al</strong>ternating named arguments as in a defstruct<br />

defined constuctor. For example, the routine to convert a vms error code into a humanreadable<br />

string:<br />

(defsysc<strong>al</strong>1 ($g<strong>et</strong>msg sys$g<strong>et</strong>msg)<br />

(msgid :in :long :required)<br />

(msglen :out :word :required)<br />

(bufadr :out :string :required)<br />

(flags :in :byte)<br />

(outadr :in :bits»<br />

(defun decode-vms-error-code {loss-code &option<strong>al</strong> (flags 15)<br />

&aux len)<br />

(using-resource (string-buffer string Z56)<br />

($g<strong>et</strong>msg msgid loss-code msglen len<br />

bufadr string flags flags]<br />

N.R. Ca1ls to SI:DEFSYSCALL. and to many other system intern<strong>al</strong> primitives work when<br />

-compiled-, but not when intepr<strong>et</strong>ed. The example above is from code in the systems"<br />

intern<strong>al</strong>s package.<br />

MC:<strong>NIL</strong>M:\N:VMSOBJ 15<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong> 299 V~IS object files<br />

29.3 Vl\1S object files<br />

To caB a procedure in a vms object file the user must do three things. define an argument<br />

interface. c<strong>al</strong>l the dynamic loader. and enable the trampolines for specific procedures. For<br />

example:<br />

(def-vrns-c<strong>al</strong>l-interface myfoo)<br />

(defun hack-foo ()<br />

(list (hack-vrns-object-file "[gjc.nil]footest")<br />

(enable-vms-c<strong>al</strong>l-trampoline<br />

'rnyfoo 'foo "[gjc.nil]footest.stb"»)<br />

(hack-foo)<br />

! S<strong>et</strong>s up for this BLISS<br />

MODULE FOOT EST =<br />

BEGIN<br />

GLOBAL ROUTINE FQO = 259;<br />

END<br />

ELUOOM<br />

s1:def-vms-c<strong>al</strong>l-1nterface name &rest arglisl<br />

Same as defsysc<strong>al</strong>l. but doesn't actu<strong>al</strong>ly look into any symbol table or create any<br />

trampoline. Only works when compiled.<br />

s1: hack-vms-object-f11e obj-jile<br />

C<strong>al</strong>ls the VMS linker on a single object file. and then reads the executable code into a<br />

bitstring in the lisp address space. Presently a VMS subprocess interface is not<br />

implementcd, (which is the easiest way for lisp to invoke the VMS linker), so instead the<br />

user is asked to execute a VMS command file lisp writes. This happens twice for every<br />

file so hacked. What a kludge.<br />

s1 :enable-vms-c<strong>al</strong>l-trampol1ne name vms-symbol slb-jile<br />

S<strong>et</strong>s up the trampJine for name using the address of the vms-symbol from the stb-file.<br />

29.4 Data Conversion<br />

At a certain level it helps to know the data representations supported by the V AX hardware<br />

itself, and what representations the various language compilers. including lisp, build on this base.<br />

L<strong>et</strong>s face it, at this point, unless you are willing to de<strong>al</strong> with such issues its best to forward<br />

specific interface reqllcsts to tile implementors. and wc'll try to at least provide a family of<br />

r<br />

cxisting examples which should make things obvious, or presolved. Even though the macrology<br />

provided by defsysc<strong>al</strong>l <strong>et</strong> aI. may m,lke it easy. it by no means m,tkes things foolproof. as any<br />

such excursions outside the lisp-world-firew<strong>al</strong>l we s<strong>et</strong> up arc frought with fmstrating debugging<br />

problems.<br />

MC:<strong>NIL</strong>MAN:VMSOBJ 15<br />

2J-DEC-8J


lowcr Ic,"cl routincs 300 <strong>NIL</strong> Manu<strong>al</strong><br />

In garhage collection. the system will not be forgiving of any violation of the mles of register<br />

and stack usage. and raw address placement.<br />

29.5 lower level routines<br />

As if the ones above weren"t low-level enough.<br />

s1: locate-symbol-table-v<strong>al</strong>ue symbol &rest stb-filenames<br />

R<strong>et</strong>urns nu)) or a fixnum.<br />

s 1 : cons truct-sys tem- symbo l-trampo 11 ne hiS-bits lo24-bits<br />

R<strong>et</strong>urns a tr.lInpoline suhr which jumps to the address specified.<br />

MC:<strong>NIL</strong>~1AN:VMSOBJ 15<br />

23-DEC-83


""WWX e m z<br />

Nil. Manu<strong>al</strong> 301 What Will Break<br />

30. What Will Break<br />

Various changes arc anticipated for future releases of <strong>NIL</strong>, just as some have taken place for<br />

this release. This chapter notes some of the significant implementation changes which have <strong>al</strong>ready<br />

occurred. and describes some which are anticipated.<br />

30.1 \Vhat Broke Since Release 0.259<br />

The single 1110S( significant change since release 0.259 is that there arc now four diffcrent<br />

formats of floating-point numhcrs. Bccausc thc new fOl11l<strong>al</strong>S do not appcar spontancously, and thc<br />

dcfault com"crsion from ration<strong>al</strong> to floating-point still produces double-float. it is unlikely that<br />

this will he particularly noticcable. "About the only possihle point of lossage here is that the v<strong>al</strong>uc<br />

of the system constant pi (page 76) is now a long-float. This is in keeping \vith the philosophy<br />

that such constants should bc in the longest format possible, and that uses which require a shorter<br />

fonnat can usc a form like<br />

(float pi O.OdO)<br />

or<br />

(coerce pi 'double-float)<br />

which will perfonn the coercion at compile time. Most othcr changcs to arithm<strong>et</strong>ic havc been<br />

additions. extensions, and fixes. For instance, the CO~MO~ LISP di\'ision and con\'ersion-tointcger<br />

functions floor, ceiling. truncate. and round now exist. Certain routines (most notably<br />

those four "division" rOlltines. and numerator. denominator. gcd. oddp. evenp. ration<strong>al</strong>. and<br />

i~tiviia:;za) hu;:c ~ccn cxtendcd t,j c\/nipk;.: numh'fs. iii ufJ~i ill dHu\\ Ill'l1lijJlIlaiioll~ 011 gdu~~i<strong>al</strong>l<br />

ration<strong>al</strong>s. See chapter 10. page 71. on numbers. for complcte information.<br />

The usc of nil in a lambda-Jist as a placeholder for an unused var is now discouraged: the<br />

compiler will issue a warning about it. The variable should be named. and then declared with<br />

the ignore declaration, as in<br />

(multi~le-v<strong>al</strong>ue-bind (foo bar baz) (mumbledy-frotz)<br />

(declare (ignore bar»<br />

... )<br />

A slight change has been made to the loop macro. The syntax<br />

(loop for x in lonnl form2<br />

do ... )<br />

which is interpr<strong>et</strong>ed as<br />

(loop for x in (progn fonnl fonn2)<br />

do ... )<br />

is being phased out. except for those "clauses" which are run tot<strong>al</strong>ly for effect, not for v<strong>al</strong>ue.<br />

Whcn multiple expressions are encountered in ~ place where a v<strong>al</strong>ue-r<strong>et</strong>urning expression is<br />

expected, a warning is issued, but the expansion is the same as before. The only "clauses" for<br />

which such multiple expressions will remain v<strong>al</strong>id are initi<strong>al</strong>ly. fin<strong>al</strong>ly, and do.<br />

There are a numher of other sm<strong>al</strong>l isolated changes which are not worth listing here, but<br />

should gener<strong>al</strong>ly be c\'ident when the code is compiled. having to do with what names are<br />

preferred for certain low-level functions, and corrections to what keyworded arguments certain<br />

functions take.<br />

MC:NII.MAN:BREAK 31<br />

23-DEC-83


What Broke Since Release 0.259 302 Nil. Manu<strong>al</strong><br />

Pathname stuff which lIsed to give you SYSSOISK as a device name now (correctly) uses its<br />

tr~inslation (specific<strong>al</strong>ly. user-workingdit-pathname). This is mentioned because it was predicted<br />

in the last release.<br />

The length (page 49) and jist-length (page 59) functions have been changed slightly. Neither<br />

finds a non-null termination of the list acceptable any more: this is in keeping with the CO~MON<br />

I.lSP definition. and (for length) is more consistent with its use as a gener<strong>al</strong> sequence length<br />

function (a list with a non-null elld is not considered a proper sequence). length continues to<br />

ghe an error if the list is circular: list-length wi1J r<strong>et</strong>urn nil when given a circular list.<br />

Certain d<strong>et</strong>:llIlts within defstruct (page 125) ha\e changed. as have certain conventions. The<br />

d<strong>et</strong>~IlJl( lype of a defstruct-defined structure is now a typed object: objects of this type can he<br />

checked t(lr wilh typep by lIsing the name of the structure as the type name. The. :conc-name<br />

option is noy,' on by dcf;mlt. and one must specify (:conc-name nil) to g<strong>et</strong> the old behaviour.<br />

Fin<strong>al</strong>ly. the keywords specified to keywordcd constnlctor macros. and to <strong>al</strong>terant macros. arc<br />

intended to be keyword symbols (interned in the keyword package). e.g..<br />

(make-person : head /7raJ :name name)<br />

<strong>al</strong>though non-keyword symbols will be accepted in the interim.<br />

Use of "destructuring" with l<strong>et</strong> is bci~g<br />

see nol-Yfl-wrillen.<br />

phased ou.t. Usc the function no/"yel-wrillell instead;<br />

Declaration scoping for speci<strong>al</strong> fonns is slightly different than it used to be. It is. in fact.<br />

~nm{'whllt mor(' {'(ln~i~t('nt th;m h('fnr('. (,h~ptl;'r ". which is n{'w. d~St:r!b{'s d('cbra!!0!1S in d('t~i!.<br />

The main difference is that declarations now scope over the "init fonns" in speciaJ forms that<br />

have them. like l<strong>et</strong>. l<strong>et</strong> •. do. prog. ctc. That is. the dc:l-specs in<br />

(l<strong>et</strong> « vo~1 v<strong>al</strong>-I) (vo,-.2 vol-2»<br />

(decl are dcl·spe~l dcl-sper-2 .•. )<br />

Jon11s . •• )<br />

that do not pertain to bindings of the variables va,..] and va,.. 2, are "in force" not only during<br />

the ev<strong>al</strong>uation of jonns. but of "101-] and "101-2. The major consequence of this is that, with<br />

declarations. l<strong>et</strong> cannot be trivi<strong>al</strong>ly turned into a lambda expression without parsing the<br />

declarations. In the expression<br />

( ( 1 ambda (va,..] va,..2)<br />

(dec 1 are dcl-spec-] dcl-spec-2 ••• )<br />

jonns • .• )<br />

v<strong>al</strong>-1 v<strong>al</strong>-2 )<br />

the declarations have no influence whatsoever on the ev<strong>al</strong>uation of v<strong>al</strong>-] and v<strong>al</strong>-2.<br />

MC:<strong>NIL</strong>~1AN:BREAK 31<br />

23-DEC-S3


~ •.-..-.......;.....~~-~~~ ~~mlll'''17Iml'I-!ltJ:!.'.rlri!r.iI1I'-'llr II.' .-Tltlr.'.1•••<br />

1717171517_1'.111 _____.-117__.-.t_______<br />

<strong>NIL</strong> Manu<strong>al</strong> 303 Future Changes<br />

30.2 Future Changes<br />

Some of these are the same as those anticipated as of Release O.<br />

30.2.1 Default Floating-Point Format<br />

The default floating point fonnat is going to change from the current double-float to singlefloat.<br />

This will <strong>al</strong>most certainly happen with the next release. The format of course could not be<br />

changed with this release and maintain any semhlance of upwards compatihility, because the<br />

I'rcrious release did not support single-float form<strong>al</strong>. Because of contagion rules. there arc re<strong>al</strong>ly<br />

just two ways one might start generating single-floats instead of douhle-tloats: when reading.. and<br />

when pertlmning some irrationa1. transcendent<strong>al</strong>. or othepA'ise awful function on ration<strong>al</strong> inputs.<br />

I f in f~lct the change matters at <strong>al</strong>l for an application (it might not if only generic arithm<strong>et</strong>ic was<br />

heing lIsed). then one could avoid problems by judicious lise of explicit cOIHersion to floating<br />

point. and by being careful to explicitly spedt: the exponentiation character in I.lSP source files so<br />

that the datatype will be explicit.<br />

30.2.2 New Pack,lge Facility<br />

The CO\1\10~ LISP package definition is fin<strong>al</strong>ly fin<strong>al</strong>. and should appear in the next release. It<br />

is unlikely that anything other than code which operates on or with packages explicitly will have<br />

to be changed, with the possible exception of references to "intern<strong>al</strong>" in one package made from<br />

another package.<br />

30.2.3 Vector-push and Vector-push-extend<br />

The argument order to vector-push and vector-push-extend will be changed so as not to<br />

be unmnemonic<strong>al</strong>ly different from that of push. Currently, the vector is the first argument, and<br />

the object to push is the second: these two will be reversed. This change became known just as<br />

release 0.259 became ready, and got lost or forgotten so never made it into this release. Ah well.<br />

30.2.4 l\lultiple V<strong>al</strong>ues<br />

In the future, <strong>NIL</strong> will "natively" support a multiple-v<strong>al</strong>ue r<strong>et</strong>unl mechanism. For it to do so<br />

requires that the compiler understand them at a moderately low level: it will be producing code<br />

for receipt of them from function c<strong>al</strong>ls, it will have to flag function ca11s which will be passing<br />

them back to another c<strong>al</strong>ler, and it must recognize and compile away <strong>al</strong>l loc<strong>al</strong> multiple-v<strong>al</strong>ue<br />

passing.<br />

~The<br />

mechanism, which has only been designed at a fairly high level, is this.<br />

Given the compiler behaviour described above. the only place which compiled code can<br />

receive multiple v<strong>al</strong>ues from is a function can (or a non-lexic<strong>al</strong> throw. but we will ignore this for<br />

the sake of simplicity in this description). This means, that when multiple v<strong>al</strong>ues arc being passed<br />

back (r<strong>et</strong>urned or generated). if we can recognize those function c<strong>al</strong>ls which arc simply being<br />

made to pass back any v<strong>al</strong>ues to their c<strong>al</strong>lers (and thus <strong>al</strong>so recognize those which are expecting<br />

MC:N(I.~·1:\N:BRE/\K 31<br />

.~:" ~ . ,', ...<br />

' " ": ,:.~ . ',.~,' .


Future Changes 304 <strong>NIL</strong> M,mu<strong>al</strong><br />

some v<strong>al</strong>ue or v<strong>al</strong>ues in particular). we can trace up the sL1ck to find the can which is ultimately<br />

expecting the mulliple v<strong>al</strong>ues. (The function c<strong>al</strong>l frames are quite fonn<strong>al</strong> and stylized in <strong>NIL</strong>)<br />

So what we do is to have the caner which is expecting multiple v<strong>al</strong>ues <strong>al</strong>locate a place for<br />

them on the stack and put a marker there, before it <strong>al</strong>locates the caU frame for the furiction. it is<br />

about to c<strong>al</strong>l.<br />

We have an function c<strong>al</strong>ls which simply pass back their v<strong>al</strong>ues as the v<strong>al</strong>ue of the function<br />

they are contained in. marked as such. so that examination of the can can d<strong>et</strong>enninc this. In the<br />

following. the c<strong>al</strong>ls to foo and bar would be so m~lrked. but baz would not:<br />

(defun frobnic~te (x y)<br />

(if (zerop xl (foo y)<br />

(mvprog! (bar x (sub! y»<br />

(baz (sub! x) y»»<br />

J f (S,lY) within bar there is a c<strong>al</strong>l (v<strong>al</strong>ues Ihis fha/). ulen a speci<strong>al</strong> subroutine goes look ing up the<br />

SLICK. finds the frame where bar is c<strong>al</strong>led. sees that it passes back its v<strong>al</strong>ues out of its c<strong>al</strong>ling<br />

function. so traces the function frame pointer to the. c<strong>al</strong>ler of frobnicate. <strong>et</strong>c.<br />

If. on the Olher hand. with baz there is a similar v<strong>al</strong>ues can. tmcing back to Ulat c<strong>al</strong>l to<br />

baz reve<strong>al</strong>s that baz is expected to r<strong>et</strong>urn only one v<strong>al</strong>ue (of interest. at most), so no further<br />

tracing is done.<br />

There are two further points of interest about this scheme. By appropriate usc of speci<strong>al</strong>ized<br />

m:1rkl'rc;: \\lh('r~ !TlllhirJ~ v~lH(,C;: are ('~p('ct('d_ fa~t dispatching may he p('rfiJrm('d for d('?!!ng W!t.~<br />

variolls situations. such as multiple-v<strong>al</strong>ue-list. for instance.<br />

A somewhat kludgey extension is to use this for things like "number c<strong>al</strong>Jingt'-one routine<br />

c<strong>al</strong>ling an0ther for (say) flonum v<strong>al</strong>ue. The one producing the flonum, instead of consing it.<br />

looks back and if the fin<strong>al</strong> destination is expccting a Honum in some speci<strong>al</strong> way (having, for<br />

instance. pre-<strong>al</strong>located a space on the stack for it). then the representation is stored there without<br />

consing. otherwise the v<strong>al</strong>ue is consed in the heap and passed back via the nonn<strong>al</strong> v<strong>al</strong>ue r<strong>et</strong>urn<br />

mechanism. The kludge involved here is that if the producer is interpr<strong>et</strong>ed code, someone has to<br />

coerce the nonn<strong>al</strong> v<strong>al</strong>ue r<strong>et</strong>urn into the hacked onc. This only is necessary when such a compiled<br />

routine is c<strong>al</strong>ling into interpr<strong>et</strong>ed code, so will probably be done by the interpr<strong>et</strong>er-trapping<br />

subroutine.<br />

The interpr<strong>et</strong>er-trap wrapper must be capable of recognizing when a v<strong>al</strong>ue has been stored<br />

"properly" into the compiled receiver. because if the producer is compiled and the interpr<strong>et</strong>er has<br />

produced the v<strong>al</strong>ue such that it got passed back "natur<strong>al</strong>ly". then it has been stored <strong>al</strong>ready<br />

without being consed, even with intervening interpr<strong>et</strong>ation!<br />

It is of note that this stack-searching is not directly an<strong>al</strong>ogous to a deep-binding variablebinding<br />

scheme. in terms· of . efficiency and paging overhead <strong>et</strong>c.~ because in the variable binding<br />

scheme the searching must be done up the entire stack (or <strong>al</strong>ist or whatever) every time. the time<br />

for each search growing in proponion to the depth of the· stack. but for this the search tenninatcs<br />

whenever va1ues are not being passed back to the previous caner.<br />

MC:<strong>NIL</strong>MI\N:BREAK 31<br />

23-DEC-S3


<strong>NIL</strong> Manu<strong>al</strong> 305 Future Changes<br />

30.2.5 Variable Naming Conventions<br />

CO\1MO!\ LISP is establishing a unifonn naming convention for system-defined param<strong>et</strong>ers and<br />

constants. Essenti<strong>al</strong>ly. <strong>al</strong>l system-defined param<strong>et</strong>ers (those variables whose v<strong>al</strong>ues are <strong>al</strong>lowed to<br />

be changed. i.e. that param<strong>et</strong>erize the behavior of the system) will have asterisks (.) at each end<br />

of their names. Thus. the variable base wiJ] become .base. (~IL uses si:standard-output-radix<br />

now anyway). and package will become .package•.<br />

1\]) system-defined constants. stich as cha~-code-limit. will not. Part of the justification for<br />

tJlis is that the compiler and inlerpr<strong>et</strong>er should he able to d<strong>et</strong>ermine when one is modifying a<br />

constant. but not a param<strong>et</strong>er. so th(.~ constants require less visu<strong>al</strong> distinction. This is in fact<br />

curremly the case. as defconstant (page 24) now works.<br />

The change of these variables is indeed going to be catastrophic to both lIsers and the :\11<br />

system itself: Note. however. that one may do (say)<br />

(who-c<strong>al</strong>ls 'package :type :v<strong>al</strong>ue)<br />

to find <strong>al</strong>l modu1cs (i.e.. restricted to compiled code) whicL reference the speci<strong>al</strong> v<strong>al</strong>ue cell of<br />

package.<br />

30.2.6 Garbage Collection-<br />

When the garbage-co])ector is finished. there wiJ] be two major incompatibilities noticeable.<br />

First. tJle format of compiled output files will change. Although initiaHy (for bootstrap and<br />

debugging purposes) old fonnat files will be accepted. it is unlikely tJlat this will still be the case<br />

by the time the garbage collector is released. Even if it is me case that such old files can be<br />

loaded. the garbage-collector will not be able to safely run afterwards. Second. mere is an<br />

incompatible change which must be made to the way unwind - protect is compiled. This cannot<br />

be handled upwards-compatibly. as it involves compiler knowledge about stack usage from tJle <strong>NIL</strong><br />

kernel, so old code might not be able to run correctly. Recompilation. of course, will fix<br />

everything.<br />

Obviously. when there is a garbage-conector. dirty operations like playing with addresses and<br />

changing types become substanti<strong>al</strong>ly more dangerous, and should be avoided by <strong>al</strong>l code except<br />

for the garbage-collector itself.<br />

30.2.7 Error System<br />

A new error system and debugger interface is being designed. The arguments to error,<br />

cerror, and/or ferror may be changed incompatibly. <strong>al</strong>though it is hoped that old uses will be<br />

able to be distinguished from new uses. condition -bind uses will have to be recompiled.<br />

Condition names may work upwards-compatibly, however. Note that now, sign<strong>al</strong> erroneously<br />

forces entry to the debugger if the condition goes unhandled: this will be changed. To enhance<br />

the ability of future code to d<strong>et</strong>ect old uses. a few conventions may be helpful:<br />

(I) The first two arguments to cerror should <strong>al</strong>ways be t or nil.<br />

(2) Always usc a string for the "error string" or "fonnat string" for <strong>al</strong>l three error functions.<br />

(MACLISP-compatible use of error can g<strong>et</strong> by WitJlout this if the "string" is a symbol, but<br />

contains at least one space in its text.)<br />

MC:<strong>NIL</strong>MAN:BREAK 31<br />

23-DEC-83


Future Changes 306 NIl. Manu4t1<br />

'Inc future debugger, which is mostly· compl<strong>et</strong>e now hut needs the new error system. will be<br />

Jnuchbcltcr able to p


·57 '17 . 2'7K2·- 37 r- -iSH'<br />

7<br />

-.<br />

XX<br />

<strong>NIL</strong> ~-1anLlaI 307 Future Changes<br />

<strong>Reference</strong>s<br />

1. Steele. G. L.. Common l.isp Refercnce Afanu<strong>al</strong>. Carnegie-Mellon University Department<br />

of Computer Science Spice Project. (in preparation). Actu<strong>al</strong>ly. it's now in-press with<br />

Digit<strong>al</strong> Press.<br />

2. Steele. G. L.. <strong>et</strong> <strong>al</strong>.. An Oveniew of Common LISP, paper prcscnted at 1982 AeM<br />

symposium on LISP and Function<strong>al</strong> Programming. 1982 ACM 0-89791-082-6/82/008/0098<br />

3. Bawden, A., <strong>Burke</strong>. G. S .. and Hoffman. C. W.. Alaclisp /:'x/ellsiol1s. MIT I.ahoratory<br />

for Computer Science. Camhridge. Mass. TM-203. July 1981.<br />

4. <strong>Burke</strong>. G. S .. I.SIl Alanu<strong>al</strong>. TM-~OO. MIT Lahoratory for Computer Science. Cambridge,<br />

Mass .. (.Julle 1981).<br />

5. <strong>Burke</strong>. G. S. .and Moon. D.. I.oop hef(]lioIlAlacro. TM-169, MIT Laborat 'ry for<br />

Computer Sciencc. Camhridgc. Mas~ .. (Janu~'ry 1981). (Revision in preparation.)<br />

6. Crocker. David H. (rcyised by). Slandard Ihr Ihe Form<strong>al</strong> of ARPA 11I1('rl1('/ Tex!<br />

Alcssagcs. N<strong>et</strong>work Information Center Request For Comments: SRI Intern<strong>al</strong>tiona1.<br />

~fcnlo Park, CA, (August 1982).<br />

7. Hawkinson. L. 8.. and <strong>Burke</strong>. G. S. Unfinished, unpublished memo/documen~1tion on<br />

the pr<strong>et</strong>ty-printer noted in section 19.5. pagc lR(): cnpicl\ of an int~rim vC'rc;:ion :tr(,<br />

included with ,It distribution kits.<br />

8. Mathlab Group. Alacsyma <strong>Reference</strong> Alanu<strong>al</strong>. MIT Laboratory for Computer Science,<br />

Cambridgc. Mass., (1977).<br />

9. Moon, D. A., AI AC LISP <strong>Reference</strong> flrlanu<strong>al</strong>, MIT Laboratory for Computer Science.<br />

Cambridge. Mass., (1974).<br />

10. Postcl, 10n. and Harrensticn. Ken, Time Protocol. N<strong>et</strong>work Infonnation Center Request<br />

For Comments: SRI Intem<strong>al</strong>tion<strong>al</strong>. Menlo Park, CA. (May 1983).<br />

11. Pratt. Vaughan R.. CGOL - an Alternative Extern<strong>al</strong> Representation for Lisp users. AI<br />

Working Paper 121. (March 1976)<br />

12. Weinrcb. D., and Moon. D., Lisp Alachille Afanu<strong>al</strong>, MIT Anifici<strong>al</strong> Intelligence<br />

Laboratory, Cambridge, Mass .• (July 1981).<br />

13. White. 1. L.. Constant Timc Interpr<strong>et</strong>ation for Sh<strong>al</strong>low-bound variables in the Presence of<br />

Alixed SPECIAVLOCAL Declar<strong>al</strong>ions. paper presented at 1982 ACM symposium on<br />

LISP and Function<strong>al</strong> Programming. 1982 ACM 0-89791-082-6/82/008/0196<br />

MC:NII.MAN:M;\NUAL 74<br />

23-DEC-83


Concept Index<br />

308<br />

Concept Index<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

&aux lambda-list keyword .•••<br />

&kc} lambda-list keyword •••<br />

&option<strong>al</strong>lambda-list keyword .•<br />

&rest\ lambda-list keyword ••<br />

a-list ••••••<br />

array • • . . • •<br />

31Ta~ disp1:lcemcnt .<br />

arr:1\ mnk .••<br />

:i!'l{'II•••••••<br />

a:-~"ri:iti()n list •••<br />

<strong>al</strong>l\ihar~ \ariahles.<br />

bad:LJlIotc .•.•<br />

bdl:l\ iour<strong>al</strong> equ<strong>al</strong>ity<br />

bCllchmarkmg.<br />

bignutn •••.•<br />

bit \cctor ..••<br />

bit-\ cctor-clements loop iteration rath<br />

bib loop iteration path. •<br />

boolean f<strong>al</strong>se. •<br />

boolean truth. •<br />

byte specifier. •<br />

byte specifier.<br />

cnaracler nilS •<br />

character code.<br />

character fonl •<br />

character s<strong>et</strong> •<br />

characters loop iteration path •<br />

closures • • . • • • • •<br />

Compilation • • • • • • • •<br />

compiled code module • • • • •<br />

conditionaJizing clause(s}, in loop •<br />

cons dot ••••<br />

cons dot ••••<br />

CRC instruction ••<br />

data type keywords. in loop<br />

decoded time •<br />

denominator • • • • • •<br />

dcstructuring. • • • • •<br />

disembodied propeny list •<br />

dispatch macro character<br />

displaced arrays. • •<br />

displaced index offs<strong>et</strong>. • •<br />

displacing arrays. • • • •<br />

DST _SITE logic<strong>al</strong> name<br />

dynamic extent •<br />

dynamic extent<br />

dynamic scope<br />

efficiency.<br />

clement type •<br />

• • • • • 14<br />

14<br />

13<br />

15<br />

• •••• 63<br />

• )03<br />

103<br />

• 103<br />

qq<br />

b.l<br />

14<br />

• .21h<br />

• 20<br />

.246<br />

• 71<br />

• .7<br />

• 164<br />

• J64<br />

6,28<br />

• •• 6<br />

84<br />

89<br />

• •••• 94<br />

94<br />

94<br />

99<br />

• 164<br />

• •• 13·<br />

• 243<br />

• 243<br />

• 154<br />

• 213<br />

• 214<br />

• 117<br />

• IS7<br />

.234<br />

• •• 4<br />

• .23.26<br />

• 39<br />

• 214<br />

• 107<br />

• • 107<br />

• 103<br />

• 241<br />

12<br />

12<br />

12<br />

.246<br />

• 103. 104<br />

clements loop iteration path<br />

empty Jist ••••<br />

equ<strong>al</strong>ity •••••••<br />

erTOr conditions. • . •<br />

extcndcd character s<strong>et</strong> •<br />

extent<br />

fCXI'TS<br />

file attribute Jist. .<br />

fhnum ••••.<br />

navurS)SlCm ••<br />

g<strong>al</strong>lssian integer.<br />

g<strong>al</strong>lssian ration<strong>al</strong><br />

gcncrafilcd \ariablcs. •<br />

~ensyming.<br />

gensym4i ••<br />

hosts •••<br />

identity of objects •<br />

implicit progn •<br />

indefinite extent •<br />

indefinite scope •<br />

, inil file • • • •<br />

integer ••••<br />

intern<strong>al</strong> time ••<br />

interned-symbols loop iteration path .<br />

interpr<strong>et</strong>er closures<br />

iteration. • • • •<br />

keyword symbols •<br />

keyworded arguments • • • • • •<br />

keywords •<br />

kill-ring . • • • • • • • • • • •<br />

lambda list keywords<br />

lambda lists • •<br />

l<strong>et</strong>Jist. • • • •<br />

lexic<strong>al</strong> scope. •<br />

lexpr. • • •<br />

lint cell ••••<br />

Ustsyntax •••<br />

logic<strong>al</strong> name. • • • • • •<br />

logic<strong>al</strong> name. DST_SITE. • •<br />

loop ••<br />

macro<br />

macro c<strong>al</strong>l •<br />

major modes. •<br />

merging and defaUlting of pathnames • •<br />

m<strong>et</strong>a key •••<br />

mixin flavors<br />

module ••••<br />

163<br />

• .6.28<br />

• •• 20<br />

229<br />

• •• 99<br />

· .• 12<br />

244<br />

205<br />

• •• 71<br />

170<br />

. 5<br />

• •. 5<br />

· .38<br />

.67<br />

• •• 67<br />

197<br />

• •. 20<br />

• •• 22<br />

.12<br />

· .12<br />

287<br />

· . 3<br />

223<br />

• •••• 162<br />

• . • . . .13<br />

144<br />

• •• 6<br />

• • • .14<br />

• •• 6<br />

257<br />

• .13<br />

• •• 13<br />

.26<br />

· .12<br />

244<br />

• •• 70<br />

214<br />

287<br />

241<br />

144<br />

• .23<br />

.23<br />

258<br />

200<br />

• • • • • • 251<br />

175<br />

• 8<br />

23-DEC-83


•• EPS 272<br />

n<br />

n<br />

Nil. Manu<strong>al</strong><br />

309 Concept Index<br />

multiplc "<strong>al</strong>ucs .••....<br />

multiple accumlilation~. in loop. •<br />

multiple expressIOn . . . . .<br />

name .••<br />

numerator.<br />

obarray. •<br />

object equ<strong>al</strong>ity<br />

oblist ..••<br />

optimi/ation .<br />

order of c\3Iu:ltion in iteration clauses. in loop.<br />

package. . •<br />

packages . .<br />

pa~sa 11 mode .<br />

patch directof)<br />

patch facility.<br />

patch file . •<br />

patch s~stem definition file .<br />

patchable system. . .<br />

path name defaults. .<br />

penasi\c declaration<br />

plist .•<br />

pname ••<br />

ppss •••<br />

print name<br />

!,rinf n~mp<br />

printed representation.<br />

propeny list •<br />

propeny lists. . • • •<br />

.• 36<br />

152<br />

146<br />

· 6<br />

· 4<br />

121<br />

.20<br />

121<br />

246<br />

147<br />

• 6<br />

121. 127. JJ7<br />

2R9<br />

280<br />

280<br />

280<br />

2RO<br />

280<br />

200<br />

.42<br />

· 6<br />

• 6.66<br />

.89<br />

.66<br />

· (;<br />

· 3<br />

.6.39<br />

39.65<br />

random numbers. .<br />

mnk. array<br />

ratio •.<br />

record ..<br />

scope .•••......•.........<br />

sequences •••.•..•.•.•.•.....<br />

sequenti<strong>al</strong> \'s par<strong>al</strong>lel binding and initi<strong>al</strong>ization. in loop .<br />

significand . . . • . . • • . . . . • . . •<br />

simple-bit.;.\,ector-elements loop iteration path<br />

simple-string-clements loop ilcr<strong>al</strong>ion path . •<br />

simple-\Cclor-clclllcnts loop iteration path<br />

speci<strong>al</strong> ....<br />

speci<strong>al</strong> variahles<br />

stack vector<br />

streams ....<br />

string . • . .<br />

string-clements loop iteration path<br />

stnlcture •..<br />

~~ n()n~ m stream .<br />

lenll logic<strong>al</strong> name. . . . . . .<br />

tenninatmg the iteration. in loop.<br />

translation table<br />

type specifier •<br />

univers<strong>al</strong>-time.<br />

\atuc equ<strong>al</strong>ity . . • . . .<br />

\ariahlc bindings, in loop.<br />

vector ••.•<br />

vector-elements loop iteration path<br />

· 86<br />

.103<br />

4<br />

7<br />

12<br />

• 48<br />

.146<br />

• 91<br />

.164<br />

.104<br />

.104<br />

II<br />

• • 11<br />

• 15<br />

.179<br />

• 7<br />

.104<br />

• 7<br />

.18:2<br />

.287<br />

.153<br />

.100<br />

· 16<br />

.234<br />

· 20<br />

.149<br />

· .103<br />

· .163<br />

23-DEC-83<br />

:':.' ~, .~ .. "<br />

,: "." ' - - ,<br />

,


Message Index<br />

310 Nil. M'lnu<strong>al</strong><br />

Message Index<br />

:ad\'ancc-pos<br />

(to bp) •<br />

. '.<br />

• 277<br />

:pp-anaphor-dispatch. • • • • • • • • • • • • • 177<br />

:dcscribc.<br />

:cqu<strong>al</strong>. •<br />

:cqu<strong>al</strong><br />

(In \'anill3- namr)<br />

:C\:ll ••••<br />

:c\hibit-sclf .<br />

• • 176<br />

• • 176<br />

• ]77<br />

• • • • • 176<br />

• 176<br />

:pp-anaphor-dispatch<br />

(to vanilla- navor) • •<br />

:pp-dispatch.<br />

:PP" dispatch<br />

(to \'anilla-flamr) •.<br />

:prinl-sclf.<br />

178<br />

177<br />

178<br />

176<br />

:c,hihit-sclf<br />

(to, anilla-fla\or)<br />

:filc-rlis1<br />

:fullcail •<br />

:gct-char<br />

(to bp). • • • • • •<br />

:gct -char-backward<br />

(to bp) •••.•<br />

:gCl-char-forward<br />

(to bp). • • • •<br />

:gct-nandlcr-tor<br />

(to ,'anilla-flavor)<br />

:init ~ with -lcnncap<br />

(to si:display-cursorpos-mixin). • •<br />

:move<br />

(to bp) •<br />

:open ••••<br />

:opcration-handled-p<br />

(to vanilla-navor) •<br />

:oustr<br />

(to si:display-cuTSorpos-mixin) •<br />

:peck -char-backward<br />

(to bp). • • • • • • • • • •<br />

• 178<br />

· .;:06<br />

• 17ft<br />

••••• 277<br />

• •• 277<br />

• •• 277<br />

.177<br />

.211<br />

.277<br />

• 181<br />

.177<br />

• •• 212<br />

• • 277<br />

:prinl-sclf<br />

(to\'anilla-na\'or) •<br />

:raw-oustr<br />

(to si:display"cursorpos-mixin). •<br />

:sclcct-nth<br />

:sclcct-nth<br />

(to vanilJa-navor) • • •<br />

:scnd -if - handl~<br />

(to vanilla-flavor) •<br />

:sct -path name •<br />

:storc-nth •<br />

:5tore-nth<br />

(to vanilla-flavor) •<br />

:sxhash •<br />

:sxhash<br />

(to vanilla-flavor) • • •<br />

:which-operations<br />

(to vanilla-flavor) • •<br />

:wrile-char<br />

(to si:di.~Jay-c:ursorpos-mixin).<br />

:write-raw-char<br />

•<br />

177<br />

212<br />

176<br />

178<br />

177<br />

181<br />

176<br />

178<br />

176<br />

177<br />

177<br />

212<br />

23·DEC·83


<strong>NIL</strong> Manu<strong>al</strong> 311<br />

Resource Index<br />

si:fab. · .................. . 207<br />

si:nam · .................. . 207<br />

si:rah. · .................. . 207<br />

Resource Index<br />

si:fah ..<br />

si:nam<br />

si:rah. .<br />

si:xah ..<br />

207<br />

207<br />

. 207<br />

••• 208<br />

23-DEC-83


Variable and Const.ant Index 312 <strong>NIL</strong> Manu<strong>al</strong><br />

Variable and Constant Index<br />

*<br />

*.<br />

•••<br />

format:*/ # -\'ar.<br />

*:autodin-ii-hash-poiynomi<strong>al</strong> •<br />

*:ccitt-hash-poJynomi<strong>al</strong> . •<br />

*:crc-16-ha,h-polynomi<strong>al</strong><br />

SIC\c:*&lrgumcnt* .•..•<br />

*hasl'*, , , .•••. , •<br />

lii1lc:"da~ -of-the-week-strings* .<br />

lime: *dd':llIl1- L1nguag.c* • •<br />

time: *default-modc*, . • .<br />

·default-p<strong>al</strong>hIl3mc-dd1ult!\*<br />

stC'\ c:*cuilur-dc\ icc-mode* •<br />

r.,: ·host- inslances*, • . • •<br />

*)u;ld- p<strong>al</strong>hnamc-defaults* .<br />

('ompilcJ:*mL':-..;;ag~-to-tcrmin<strong>al</strong>'! .<br />

·modules* . , • • • . • • • ,<br />

limc:·monlh-strings· . . • . .<br />

compiicr:*opcn-compilc-carcdr-switch<br />

compiler:*upcn -compiic-xref-switch •<br />

·package· . ., •••••<br />

*random-state*, • , • , •<br />

*rcad-dcfault-float-format*•<br />

·scr<strong>al</strong>ch-pathnamc-dcfauiLS*<br />

umc:*s),stcm-lImc- kludgc· •<br />

·limclOnc*, •• , ••••<br />

form<strong>al</strong>: *top-char-printer •<br />

-trace-output·<br />

+ ..<br />

++ .<br />

+++<br />

format:atsign-flag • • • • • •<br />

*:autodin-ii - hash -polynomi<strong>al</strong> •<br />

base<br />

•••••••••<br />

.288<br />

.288<br />

• 288<br />

• • • 191<br />

• • 117<br />

• •• 117<br />

• • • 117<br />

• 274<br />

• • 305<br />

• •• 1.'1<br />

• •• 23()<br />

• • 236<br />

• •• 202<br />

• • 278<br />

• •• 202<br />

• 201<br />

• • 24()<br />

• •. 123<br />

• 237<br />

• 245<br />

• • 245<br />

• • 305<br />

• • 86<br />

4. 72<br />

• • 202<br />

• .241<br />

• •• 238<br />

• • 191<br />

• 179<br />

• • 288<br />

• •• 288<br />

• 288<br />

• • 195<br />

• • 117<br />

• •• 305<br />

double-float-epsilon<br />

Constant •••••<br />

double-float-negative-epsilon<br />

Constant .••<br />

error-output. • •<br />

• .93<br />

• .93<br />

179<br />

format:*/#-\'ar • . 191<br />

fomlat:*top-char-printef. 191<br />

u)mlat:atsig.n- flag.. .<br />

lQ5<br />

fom131:colon-flag. )Q5<br />

1k-hoSl-instances* • 202<br />

intern<strong>al</strong>-lime-units- per-~ond<br />

('onstant. • • • • • •• • • • • . • • • • 223<br />

lcaSl-nCg


NIl. Manu<strong>al</strong><br />

313 Variahle and Constant Index<br />

most - posit i\"c-Iong - float<br />

Constant ..•....<br />

most - posit ivc-shon - float<br />

Constant. . . . . . .<br />

most-positi\"c-singlc-float<br />

Constant.<br />

msgfilcs.<br />

package.<br />

pi<br />

Constant.<br />

prinlc\ cl<br />

query-io<br />

rcadlahle<br />

~hon - float -epsilon<br />

Constant ...•<br />

short- flo<strong>al</strong>-ncg:ni\c-cpsilon<br />

Constant ..... .<br />

si:chars~ nl:nSm_3Jpha<br />

Constant ....•.<br />

si: charsyntaxSm_both_case<br />

Comitant ..•.•.<br />

si:charsyntax$m_digit<br />

Constant .•.••.<br />

c;i~('h:trc;ynt:n~m~r~!,hir<br />

Cons1.3l1t ..•...<br />

si:charsynt3xSm_lowcr_case<br />

Constant ...•..••<br />

si:charsyntaxSm_standard<br />

Constant. .•.....<br />

si:charsynLaXSm_upper_case<br />

Constant. ••••••.<br />

• 92<br />

.92<br />

• 92<br />

ISO<br />

122.305<br />

.76<br />

17h<br />

179<br />

• 218<br />

.93<br />

.93<br />

102<br />

102<br />

102<br />

101<br />

102<br />

10~<br />

101<br />

si:charsyntax$v_<strong>al</strong>pha<br />

Constant .•.•..<br />

si:charsynLaX$\'_both_case<br />

Constant •..•<br />

si:charsyntax$,,_digit<br />

Constant ••.•<br />

si:charsyntax$v -.sraphic<br />

Constant •.•••<br />

si:charsyntaxSv_Iowcr_case<br />

Constant ..... .<br />

si:charsyntax$,_standard<br />

Constant ..... .<br />

si:l'harsynt~lx $\ _upper_case<br />

Constant •.<br />

si:dchug -input. . . . . .<br />

si:dchug-output . . . . .<br />

si: lisp-dchuggcr-on -exceptions.<br />

si:loop-usc-systcm -destnlctllring? .<br />

si:standard-output -radix<br />

singlc- flU:ll-Cpsilon<br />

Constant .•....<br />

singJc- float -neg<strong>al</strong>i\c-cpsilon<br />

Constam .•<br />

standard-input. • • • .<br />

standard-output . • . .<br />

si:standard-outpul-radix<br />

stcvc:·argumcnt*. • . •<br />

~!~v~: *~di! O!'-dC':ice-med<strong>et</strong>ermina\-io<br />

. • . • . . .<br />

time: *day -of -the-week -strings·<br />

time: ·default -Ianguage* .<br />

timc:*defau1t-modc· .•.<br />

time:*month-slrings*. • •<br />

time:·system -time-kludge-<br />

.102<br />

.102<br />

.102<br />

.101<br />

.102<br />

.102<br />

.101<br />

.180<br />

.180<br />

.21JO<br />

.]59<br />

• •.. 305<br />

. •......... 93<br />

93<br />

· •.. 179<br />

• .179. 195<br />

.305<br />

.274<br />

.278<br />

.179 "<br />

.237<br />

• •• 236<br />

.236<br />

• •.. 237<br />

• .241<br />

23-DEC-83


Function. Macro. and Speci<strong>al</strong> Form Index 314<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

Function, Macro, and Speci<strong>al</strong> ForD1 Index<br />

%char-downcase-code. •<br />

%char-upease-code ••••<br />

%comcn-d_float-to-time<br />

'kom:cn-limc-lo-d_float<br />

%digil-char-in-radix-p<br />

%digil-char-to-weight .<br />

%digit-wcight-to-char •••••••<br />

%dph ..•.•.••.<br />

s~ s:ri·{j\llllm-a.,h -with-o\ crflow-lrapring .<br />

s~:-.:(·:,lhlllllll-dirkrcllrl·-wilh-mcrl1ow-lraJlJling.<br />

s~s:('(/n\lIll1n-JllllS-\\ ilh-mcrllo\\ -tr


NIl. Manu<strong>al</strong> 315 Function. Macro. and Speci<strong>al</strong> Form Index<br />

a"h. .83 cdaadr . · 56<br />

a"h& . .89 cdaar · 56<br />

asin .77 cdadar • .56<br />

ao;inh. . 18 cdaddr • .56<br />

<strong>al</strong>iSOC . • 64 cdadr · 56<br />

aC\sq • 64 cdar • · 56<br />

atan .11 cddaar • · 56<br />

atanh. .18 cddadr • · 56<br />

cddar .56<br />

bigp .19 cdddar • · 56<br />

bil . 109 cddddr. · 56<br />

hil-and . 109 cdddr 5h<br />

hil-andd 109 cddr. · 56<br />

bil-<strong>al</strong>ldc~ . 109 cdr · 56<br />

bit-C · 95<br />

steve:c-u-onlyt 278 char>=. • 95<br />

c .... r . 56 character • .96<br />

caaaar .56 characterp . • 19<br />

caaadr .56 check-argo • 230<br />

caaar • .56 check-type .229<br />

caadar .56 clear-input .183<br />

caaddr • 56 clcar-output • .185<br />

caadr. .56 dose. . .181<br />

caar<br />

· . . • 56 fs:close-<strong>al</strong>l-files • . . .202<br />

cadaar .56 closure. .13<br />

cadadr .56 cJosurep .13.19<br />

cadar. • 56 cJrha~ • .118<br />

caddar • 56 cnarnef • .181<br />

cadddr .56 code-char .96<br />

caddr. · . .56 coerce . 9<br />

cadr • 56 comfile • .245<br />

car • . .56 compile .245<br />

case • 29 coml'ilc-file • .244<br />

~cq. . .30 si:compilc-load-p<strong>al</strong>ch. .283<br />

catch • • 35 si:compilc-patch . .283<br />

cdaaar . 56 compiler-l<strong>et</strong> • .245<br />

2J-DEC-8J


Function. Macro. and Speci<strong>al</strong> Fonn Index<br />

316<br />

<strong>NIL</strong> Manu<strong>al</strong><br />

C'omplex •.•<br />

concatenate. •<br />

cond •.<br />

conjugate<br />

cons •• '. . .<br />

consp ..<br />

si:conslrucl-system-symbol-trampoline<br />

timc:comcn-\ms-timc-to-uni\'crs<strong>al</strong>-time. •<br />

cop~ -<strong>al</strong>ist<br />

COP}-Iist •••<br />

cop~-scq ••<br />

co('~ -synlhol •<br />

C'OJl~ -tree . .<br />

COp~3IiSt ••.<br />

co('}symhol<br />

cn(')trce.<br />

C(}l\. • •<br />

cosh ••<br />

count ••<br />

count-if.<br />

count-if-not .<br />

cre<strong>al</strong>c-rcadL1ble. •<br />

cursorpos .••<br />

79<br />

50<br />

28<br />

75<br />

57<br />

18<br />

.300<br />

• 240<br />

59<br />

59<br />

51<br />

66<br />

59<br />

59<br />

69<br />

59<br />

77<br />

78<br />

52<br />

52<br />

52<br />

219<br />

• 181.210<br />

time:day-of-the-week •<br />

• ••• 238<br />

time:day-of -the-week-string •<br />

• ••• 237<br />

lime:daylight-savings-p • . •<br />

• .238<br />

timp:n:tylight-c;::winrl;-timf'-!'<br />

· 21~<br />

dehu~ •<br />

.222<br />

deer. ...•<br />

• ••• 39<br />

declare •••<br />

• • .41,243<br />

decode-float. •<br />

• 91<br />

decode-univers<strong>al</strong>-ljme •<br />

· •• 235<br />

si:def-,-ms-c<strong>al</strong>J-inlcrface ••<br />

• .299<br />

dcfconstant. • • •<br />

• ••• 24<br />

deffiavor ..•••<br />

• • 171.173<br />

define-fonnat-op •<br />

• ••• 194<br />

define-loop-macro<br />

• 157<br />

define-loop-path •<br />

• • 164<br />

definc-loop-sequence-path. •<br />

• •• 163<br />

defmacro .••••••<br />

• • 23<br />

defm<strong>et</strong>hod. • • • • •<br />

• 175<br />

dcfmcthod-primitive ••<br />

• ••• 17S<br />

defparam<strong>et</strong>er. • • . •<br />

• • 24<br />

defstruct. • • • •••<br />

• 125<br />

defstruct - define-type<br />

• .138<br />

si:defsysc<strong>al</strong>l. •<br />

• • 298<br />

defun •<br />

· .22.243<br />

defvar. • • •<br />

• • 24<br />

del<strong>et</strong>e. • ••<br />

• • 53<br />

del<strong>et</strong>e- file • •<br />

.203<br />

del<strong>et</strong>e-if. • .<br />

S3<br />

del<strong>et</strong>c-if-not •<br />

53<br />

deposit - byte .<br />

90<br />

deposit-field •<br />

86<br />

describe •••<br />

• • 222<br />

si:dctennine-and-sct-tennin<strong>al</strong>-type • • • • • • • • 211<br />

difference. •<br />

digit -char. •<br />

digil-char-p.<br />

do .•<br />

do· •••<br />

dolist •••<br />

dolimes •.<br />

doveelor<br />

dpb •<br />

dpb&.<br />

ed .•<br />

stC\ e:ed-losc.<br />

stcvc:cd-warn<br />

Slc\'c:cd-warning. .<br />

stc\'c:cditor-hind-kcy .<br />

s1e\c:cditor-dcfun-kcy<br />

eighth • • •<br />

c1a('scd -time. . • • .<br />

ell. . . • . . . . .<br />

si:cnablc-l"ms-caH-lrampoline<br />

ene'ode- univers<strong>al</strong>-time.<br />

si:entcr-rcadtablc.<br />

eq ••<br />

eql ••<br />

equ<strong>al</strong>.<br />

equ<strong>al</strong>p ••<br />

e\'2~-whef! .<br />

even}'<br />

c'-er) •••<br />

exhibit ••<br />

exit -and-run-prOiram<br />

exp<br />

expt •••<br />

tboundp<br />

fceiling • •<br />

moor .••<br />

fifth • • •<br />

file-author<br />

file-crcation -date.<br />

file-length.<br />

filepos • •<br />

fill. • • •<br />

fiU-pointer<br />

find •••<br />

find-if ••<br />

find-if-not<br />

finish-output<br />

si:finish-patch • •<br />

first • • • • • • •<br />

Slc\'e:first-line1. •<br />

fixnunlp • • • ~ • •<br />

fixp •••<br />

float ••.<br />

noat-digit~<br />

float-precision ••<br />

• •• 74<br />

• .97<br />

• ••••.••• 97<br />

· • . . . . .33<br />

· • • . . . • . .33<br />

.33<br />

• .-32<br />

• •• 33<br />

· .85<br />

• •••.•••• 89<br />

24q<br />

• 277<br />

277<br />

278<br />

274<br />

275<br />

.56<br />

223<br />

.4Q<br />

299<br />

235<br />

219<br />

.20<br />

• ••• 20<br />

• 20.176<br />

. ••••• 21<br />

· . 25. 24~<br />

• •• 73<br />

· .55<br />

222<br />

289<br />

.76<br />

.76<br />

• ••• 68<br />

• .81<br />

• •• 81<br />

••••• 56<br />

• 203<br />

203<br />

• •••• 203<br />

203<br />

• ••• 52<br />

106<br />

• •• 51<br />

• .51<br />

· .51<br />

184<br />

283<br />

• ••• 56<br />

• 278<br />

.19<br />

.19<br />

• •• 78<br />

• •• 92<br />

.92<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong><br />

317 Function, Macro. and Speci<strong>al</strong> Fonn Index<br />

float-radix.<br />

float-sign<br />

floatp ..<br />

flonump.<br />

floor ..<br />

fmakunbound .<br />

force-output.<br />

format ..•.<br />

fonnat -eharpos.<br />

(omlat- fl<strong>al</strong>e. .<br />

fon11:I1- form feed •<br />

form:1l- fresh -line. .<br />

fOrm:lI-lcprinc .<br />

fonnm-lincl .<br />

fo01131- prin 1. .<br />

funn:1t-pnne.<br />

form<strong>al</strong>-Iah-to<br />

form<strong>al</strong>-Icrpri. . .<br />

fom1<strong>al</strong>-tyo .<br />

form<strong>al</strong>-) -or-n-p.<br />

fomlat -ycs-or-no-p<br />

fourth . • .<br />

fquery ..<br />

fresh-line.<br />

fround ••<br />

fs:close-<strong>al</strong>l- files<br />

(c;:process- in -load-environment. •<br />

f~C' •..<br />

«.ct...•<br />

("ymc\,<strong>al</strong><br />

ftruncate<br />

func<strong>al</strong>l .<br />

gcd .••<br />

gcnsym •<br />

gcntcmp.<br />

g<strong>et</strong> •••<br />

g<strong>et</strong> - a-byte.<br />

g<strong>et</strong>-a-byte-2c ••<br />

si:gct-c<strong>al</strong>l-m<strong>et</strong>ers. • •<br />

g<strong>et</strong>-decoded-time.<br />

g<strong>et</strong>-internai-rcai-time.<br />

g<strong>et</strong>-intcrnai-run-time •<br />

gct-output-strcam-string. • •<br />

gct-pnarne. • •<br />

s<strong>et</strong>-privileges • • • •<br />

g<strong>et</strong>-properties • • • •<br />

si:g<strong>et</strong> -system-version •<br />

si:g<strong>et</strong> -system -version -list<br />

·gct-univers<strong>al</strong>-time<br />

g<strong>et</strong>f •••••<br />

g<strong>et</strong>hash •••••<br />

si:gctjpi-string • •<br />

si:g<strong>et</strong>jpi-v<strong>al</strong>ue •<br />

gcll. • • • ••<br />

si:gctsyi-string .<br />

si:g<strong>et</strong>syi-v<strong>al</strong>ue •<br />

.91 glob<strong>al</strong>i7.e ...<br />

.92 go •.•••.<br />

.19 graphic-char-p<br />

• 19 grcatcrp .••<br />

.79<br />

.68<br />

184<br />

187<br />

196<br />

196<br />

196<br />

1%<br />

1%<br />

196<br />

195<br />

195<br />

196<br />

196<br />

195<br />

197<br />

197<br />

.56<br />

}97<br />

185<br />

.81<br />

202<br />

206<br />

.Ql<br />

.69<br />

.69<br />

. 81<br />

.30<br />

. 75<br />

.67<br />

.67<br />

.65<br />

III<br />

111<br />

•• 225<br />

235<br />

• 223<br />

• 223<br />

182<br />

.69<br />

233<br />

.40<br />

282<br />

•••••• 282<br />

•••••••• 235<br />

.39<br />

US<br />

242<br />

241<br />

.69<br />

242<br />

242<br />

si:hack-vms-ohjcct~file. .<br />

haipart .•..•<br />

hash -table-count<br />

hauiong ....<br />

haulong& ...•<br />

host-software-typc .<br />

if ...<br />

imagpan<br />

illcf ..<br />

init- file-pathnamc .<br />

si:initi<strong>al</strong>i/c-patch-s},stcm<br />

int-char ....•<br />

intcger-decode- flo<strong>al</strong><br />

inl<strong>et</strong>! ," r-)ength .<br />

intcrr ...<br />

intern-soft<br />

intersection •<br />

isqn .•<br />

last •<br />

stc\'c:last-linc? .<br />

timp"I:llO:t .IO:llnn::ly-in-:l!"ril<br />

timc:last-sunday-in-uctoher .<br />

tcm .<br />

Idb •••<br />

ldb& ••<br />

Idh-tcst<br />

IdiIT •••<br />

time:lcap-year-p. •<br />

length<br />

lessp.<br />

l<strong>et</strong> •••<br />

l<strong>et</strong>· •<br />

lexpr-func<strong>al</strong>l<br />

lexpr-send • •<br />

lexpr-scnd - forward.<br />

stcve:line-next. • •<br />

steve:line-previous •<br />

lisp-implementation-type •<br />

lisp-implementation-version •<br />

list • • •<br />

list· • • •<br />

list -length<br />

listen<br />

listp. • •<br />

load .••<br />

load-byte.<br />

load -patches<br />

si:loc<strong>al</strong>e-symboi-tab)c-v<strong>al</strong>uc •<br />

log ••<br />

logand ••••••••.•••<br />

.122<br />

• 34<br />

· 94<br />

· 74<br />

.299<br />

· 84<br />

.118<br />

· 84<br />

• 89<br />

.232<br />

• 2R<br />

5<br />

· 39<br />

.200<br />

.284<br />

.96<br />

· 92<br />

· 83<br />

.122<br />

.122<br />

• 62<br />

.77<br />

· 58<br />

.278<br />

.'~Q<br />

.239<br />

· 75<br />

• 85<br />

· 89<br />

· 85<br />

.60<br />

.238<br />

· 49<br />

• 74<br />

• 26<br />

• 26<br />

• 31<br />

.172<br />

.173<br />

.276<br />

.276<br />

.232<br />

.232<br />

• 57<br />

• 57<br />

· 59<br />

.183<br />

• 18<br />

.204<br />

.90<br />

.281<br />

.300<br />

.76<br />

· 81<br />

23-DEC-83


Function. Macro. (Iud Speci<strong>al</strong> Fonn Index<br />

J18<br />

Nil. Manu<strong>al</strong><br />

logand& .•.<br />

Jogandcl ••<br />

. Jogandc 1 &. .<br />

logandc2 •••<br />

Jogandc2& ••<br />

Joghitp •<br />

logbitp&.<br />

logcounl.<br />

logcount&<br />

logcqv ••<br />

Jugcq\& •<br />

Jo~ior .•<br />

Jogior& •<br />

lognand •<br />

Jognand&<br />

Jugnm .•<br />

Jognor& •<br />

lognnt. .<br />

lognot& •<br />

logon". ..••.<br />

logorcl& •••<br />

lugurc2 .<br />

logorc2&.<br />

logtest ••<br />

loglcst& •<br />

logxor. • • •<br />

logxor& •<br />

lonr-c.;itl'-n:unl'<br />

si:lnokup-rcadlablc<br />

1001' • • • • • •<br />

loop-finish. • • •<br />

si:lool'-gcntemp. .<br />

si: 1001'-namcd - ,'ariable.<br />

si:loop-ta~soc. •<br />

si:loop-tequ<strong>al</strong>. •<br />

. si:loop-tmcmber<br />

lower-case-p .•<br />

machine-instance.<br />

machine-type •<br />

macro .••••<br />

make-array. • .<br />

make-bit-vector<br />

steve:make-bp •<br />

make-char •••<br />

si:make-fab •••<br />

make-hash-table •<br />

makc-instance ••<br />

stc\'c:make-line. •<br />

make-list ••<br />

si:make-nam. • •<br />

si:makc-rnb • .<br />

make-random-state • •<br />

l'Otc"c:makc-scrcen-im3ge •<br />

maL:e-sequence. • • • •<br />

makc-string • • • • • •<br />

maL:e-Slring-inpul-Slrcam<br />

88<br />

82<br />

88<br />

82<br />

88<br />

81<br />

89<br />

83<br />

89<br />

81<br />

88<br />

• • • • • 81<br />

RR<br />

82<br />

88<br />

82<br />

88<br />

83<br />

89<br />

8~<br />

88<br />

82<br />

88<br />

83<br />

89<br />

81<br />

88<br />

· :n,<br />

• 218<br />

• 144<br />

• 153<br />

• 166<br />

· 166<br />

.1b6<br />

• 166<br />

• 166<br />

• 9S<br />

• 232<br />

• 232<br />

• 24<br />

• 103<br />

• • 110<br />

• ••• 275<br />

.96<br />

• 207<br />

• ••• 118<br />

• • 171.173<br />

• 276<br />

• 58<br />

• '2D7<br />

• • 201<br />

• 86<br />

· 279<br />

.50<br />

• • 114<br />

.182<br />

makc-string -output-stream.<br />

makc-~)mhol • • • •<br />

makc-sy nonym -stream<br />

make~vcctor. •<br />

si:make-xab •<br />

makunbound.<br />

map .•.<br />

mapaUfilcs.<br />

mapatoms.<br />

mapc .••<br />

mapcan •<br />

mapcar •.<br />

mapcon ..<br />

mapl •••<br />

maplist· •<br />

mask-field<br />

n13X<br />

•••<br />

mad ....<br />

max& •<br />

. mcmber ••<br />

memq • • • ••••<br />

mcrgc-pathnamc-dcfauits<br />

min.<br />

minS ••<br />

min& .•<br />

minus<br />

minu~ ••<br />

m~ ...<br />

timc:modc-languagc- fClch •<br />

si:modulc-sourcc- file .<br />

time: month -length<br />

timc:month-string • • • • •<br />

timc:moonphase • • • • • •<br />

multiple-v<strong>al</strong>ue. • •<br />

multiple-v<strong>al</strong>ue-bind<br />

multiple-v<strong>al</strong>ue-list .<br />

multipie-v<strong>al</strong>ue-prog1<br />

multiple-v<strong>al</strong>ue-s<strong>et</strong>q •<br />

steve:mx-prompter •<br />

name-char<br />

namestring<br />

nbutlast ••<br />

ncone. • •<br />

noons •••<br />

si:new-p<strong>al</strong>Ch-system<br />

nibble •••••<br />

nibble-2c ••<br />

nintersection •<br />

ninth. • • • •<br />

not •••••<br />

stcve:not -buffer-begin<br />

!neve:nol-buffer-end<br />

stcve:not-first-line •<br />

stcve: not -last-line • • • •<br />

notany ••••••<br />

notc-modute-pathname • •<br />

182<br />

.b6<br />

182<br />

108<br />

207<br />

• •. 68<br />

32.54<br />

204<br />

122<br />

· . .31<br />

• •• JI<br />

• •• 31<br />

. .31<br />

• • • -' 1<br />

.31<br />

• •. 85<br />

.74<br />

• •• 91<br />

• •• 87<br />

.61<br />

.61<br />

201<br />

.74<br />

.91<br />

.87<br />

.75<br />

.73<br />

• •• !H<br />

2~n<br />

221<br />

238<br />

237<br />

238<br />

• •• 37<br />

• • .37<br />

•• 37<br />

.37<br />

.37<br />

279<br />

• •• 97<br />

199<br />

.59<br />

.58<br />

• •• 57<br />

284<br />

• • 111<br />

111<br />

• •• 62<br />

.56<br />

• •• 28<br />

278<br />

278<br />

278<br />

278<br />

• •• S5<br />

124<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong><br />

319 FunClion. Macro. and Speci<strong>al</strong> Form Index<br />

si:nntc-primitivc-font .<br />

notc\ct).<br />

nrcconc.<br />

nrc\"crsc.<br />

nscl-di/Tcrcnce.<br />

n~t -cxclusi,"c-or .<br />

n~ring-down~c ..•<br />

nstring-upcasc • •<br />

nsublis •••<br />

nsubst ...<br />

nsubstitute. .<br />

nsubstitute-if<br />

osubslillltc-if -not.<br />

nth .•.•...<br />

SIC\ c:nth-ncxl-Iine<br />

stc\c:nlh-prc\ inus-line<br />

nthcdr .<br />

null ••<br />

numbcrp<br />

mmion<br />

oddp .•<br />

opcn ••<br />

or •••<br />

ouslr •<br />

stc"c:overwrile-done<br />

ste\c:merwrilc-homc •<br />

~1(,\(,:O\'f'rwrir('-~~rt "<br />

SIC\c:o\,crwrilc-tcrpri .<br />

si:paclcage-symbolconc.<br />

si:pag~faull-count.<br />

pairlis ..•<br />

pairp ••••••<br />

pathname ••••<br />

pathnamc-device •<br />

pathname-directory •<br />

pathname-host •<br />

pathname-name • •<br />

pathname-type. •<br />

pathname-version.<br />

peck-char ••.••<br />

pkg-create-package •<br />

pkg - find -package.<br />

pkg-goto<br />

plist ••<br />

plus ••<br />

pJusp ••<br />

stcve:point. •<br />

stcve:point-selected. •<br />

pop ..•.<br />

position •••••<br />

position - if. . • .<br />

posilion-if-nol. •<br />

utils:pp-inlo-file •<br />

prctty-prin 1 . • •<br />

prcny-prinl-datum. •<br />

WI<br />

· .55<br />

.58<br />

.52<br />

.62<br />

.62<br />

115<br />

115<br />

· .61<br />

.60<br />

. 54<br />

.54<br />

• •• 54<br />

.57<br />

· . 276<br />

· 276<br />

.57<br />

• 18<br />

.19<br />

.62<br />

.73<br />

180. 211<br />

.29<br />

• . 185<br />

• • 279<br />

• 279<br />

27Q<br />

279<br />

.70<br />

• 224<br />

• •• 64<br />

.19<br />

• • 199<br />

· 199<br />

199<br />

• 199<br />

••• 199<br />

199<br />

• • 199<br />

••• 183<br />

• • 122<br />

. ...... . 122<br />

122<br />

.69<br />

.74<br />

.73<br />

276<br />

••• 276<br />

••••••••• 38<br />

.51<br />

.51<br />

. 51<br />

228<br />

186<br />

187<br />

prclty-print •<br />

prclly-print-datum.<br />

print<br />

prine. . • • . • • .<br />

print •.••...<br />

limc:print -bricf-univers<strong>al</strong>-timc. •<br />

lime:print-current-datc. . • . .<br />

limc:prinl-current-mail-fonnat -date<br />

time:print-current-moonphase<br />

time:print-currcnl-time •<br />

timc:prinl-datc • .<br />

si:print-hcr<strong>al</strong>d. . •..<br />

utils:prillt - into-file. . .<br />

timc:prim-moonphasc<br />

f1rinl-s~ stcm - hisIOt)" . .<br />

print - s~ stcm -modi fic<strong>al</strong>ions<br />

tiflle:print-lime • • • • • .<br />

timc:print-uni\crs<strong>al</strong>-datc .<br />

timc:print -univcrs<strong>al</strong>-mail- format-d<strong>al</strong>e. .<br />

timc:print -uni\crs<strong>al</strong>-lime<br />

probc-file . . • • . • . . . .<br />

proceed-nil. . . • • . • . • .<br />

tkproccss-in-Ioad-cnvironmenl<br />

proclaim •••••<br />

prog .<br />

prog*<br />

progl<br />

nroo') r· -4,;'-<br />

progn<br />

prog"<br />

progw<br />

progwf ••<br />

pmgwq.<br />

provide.<br />

ps<strong>et</strong>q<br />

push.<br />

putprop<br />

quit •••<br />

quotient •<br />

random ••<br />

rassoc ••<br />

rassq •••<br />

ration<strong>al</strong>.<br />

ration<strong>al</strong>ize<br />

si:re-edit -p<strong>al</strong>ch<br />

read •••••<br />

stevc:rcad-buffer-name •<br />

read-byte •••••<br />

read-char •••••••<br />

5tc\'e:rcad-file-name<br />

rcadline • • • • • • •<br />

steve:rc<strong>al</strong>-arg-sup? •<br />

rc<strong>al</strong>p<strong>al</strong>1 .•••••<br />

.187<br />

.un<br />

.185<br />

.185<br />

.185<br />

.236<br />

.236<br />

.236<br />

.239<br />

.235<br />

.236<br />

.282<br />

.228<br />

.239<br />

· .281<br />

.281<br />

.235<br />

.2''''<br />

.2~, ,<br />

.235<br />

.203<br />

.llN<br />

.206<br />

46.243<br />

· . 35<br />

35<br />

22<br />

:22<br />

22<br />

27<br />

• . 27<br />

27<br />

· 27<br />

.123<br />

· 26<br />

38<br />

· 65<br />

.289<br />

75<br />

. ••. 86<br />

· .64<br />

. ••• 64<br />

• 78<br />

. ••••• 78<br />

• .283<br />

.184<br />

.279<br />

.184<br />

· .183<br />

.279<br />

.184<br />

• .278<br />

· • 5<br />

.239<br />

tirne:rcgular-amcrican-daylight-saving.s-time-p .<br />

rem •••••••••••••.••••• ". 80


Function. Macro. and Speci<strong>al</strong> Fonnlndex<br />

320<br />

Nil. Manuell<br />

remaindcr<br />

remf •.<br />

rcmhash ••<br />

remmc ••.<br />

rcmo\c-if ••<br />

remmc-if -nOl<br />

rcmpTop ••<br />

rename- filc<br />

rcplacc •••<br />

require •.<br />

si: r~q uirc-charartcr<br />

l'i: rcquin:-l'haracter-Jhnum •<br />

rl'!\~l- fi 11- poi III er<br />

rest ••.••<br />

r<strong>et</strong>urn .•••<br />

r<strong>et</strong>urll-from<br />

rC\3ppcnd .<br />

rC\'crsc . • •<br />

si: mlsSclose<br />

si:nns~n)\)ncct<br />

si:rmsScrcate .<br />

si:nnsSddc(c .<br />

si:nns$disconncct .<br />

si:rmsSdisplay. •<br />

si:rmsSenter • •<br />

si:rms$crase •<br />

si:rmsScxlcnd.<br />

si:rms$find. .<br />

si:nnsSnush<br />

si:rmsSfrcc. •<br />

si:rms$g~t • •<br />

si:mlsSnxt\'ol. • • • • •<br />

si: mls$opcn<br />

~i:rmsSparsc •<br />

si:nns$put •<br />

si:nnsSrcad.<br />

si:rms$reJcase. •<br />

si :nnsSrcmove<br />

si: nnsSrename<br />

si: rmsSrcwind.<br />

si:rms$scarch •<br />

si:rmsSsctddir.<br />

si:nns$space . • • • • •<br />

si:rmsStrunc •<br />

si: rms$update.<br />

si:nns$wait.<br />

si:nns$write • • • • • •<br />

room •<br />

rot<strong>al</strong>ef.<br />

round.<br />

rpJaca •<br />

rplacd •<br />

runtime •••<br />

sarncpnamcp •<br />

SlC\'C:savc-<strong>al</strong>J - files.<br />

sbit. • • • • • •<br />

• • 80<br />

• • 40<br />

• 118<br />

53<br />

53<br />

53<br />

65<br />

• 203<br />

52<br />

123<br />

• • • • • 97<br />

97<br />

• • lOb<br />

57<br />

• • • • • 34<br />

34<br />

S8<br />

52<br />

• 208<br />

· • 20R<br />

.208<br />

• 208<br />

• 208<br />

• 208<br />

.209<br />

• 208<br />

• 208<br />

· ?OR<br />

• 208<br />

• 208<br />

.208<br />

.208<br />

• • 20R<br />

.209<br />

.208<br />

• 209<br />

.208<br />

.209<br />

.209<br />

.208<br />

• .209<br />

• 209<br />

.209<br />

• 209<br />

.209<br />

• 209<br />

• 209<br />

.234<br />

39<br />

79<br />

56<br />

••••• 56<br />

.223<br />

.66<br />

• 277<br />

• 109<br />

sc<strong>al</strong>c- n03t •<br />

schar •••<br />

second ••<br />

stcvc:scJcct -I'oint .<br />

!.1c"c:sclcct-point-in-currcnt-window<br />

seiCt1q . • • • • ••••<br />

send ••••<br />

send-forward<br />

s<strong>et</strong> •••••<br />

s<strong>et</strong>-di ffcrcnce<br />

s<strong>et</strong>-cxclusivc-or •<br />

sel-ldb& .•••<br />

si:~t -~nch-cO\·irollmcnl. .<br />

s<strong>et</strong> -I'rhilcgcs . • • • . • • • • • .<br />

si:sct-!\ystcm-st:nus. •<br />

sct-tcmlin<strong>al</strong>-typc.<br />

self •.<br />

s<strong>et</strong>l'list • •<br />

selq .•<br />

~tsynlax .•••.<br />

lICtsyntax -sharp-macro. •<br />

~c\"c:sctul'-modc-arca<br />

seventh ..<br />

5gner .•••••<br />

shillf. • • • • •<br />

short-site-name<br />

si:show-c<strong>al</strong>l-mclcrs. •<br />

Q:lJ.jr1 .<br />

si:%syi ••••••<br />

si:abon-p3Ich . • • •<br />

si:add-cscape-char-syntax •<br />

si:add -list-syntax. • • •<br />

si:add-numhcr-syntax ••<br />

si:add-packagc-!o"yntax •<br />

si:add-patch. • • • • •<br />

si:add-prcfix-op-macro •<br />

si:apTopos-@cnerate. • • • • • • •<br />

si:compilc-load-patch. • •<br />

si:compile-patch • • • • •<br />

si:construct-syslcm-symbol-trampoline. •<br />

si:def-vms-c<strong>al</strong>l-intcrface. • • • • •<br />

.91<br />

114<br />

.56<br />

276<br />

276<br />

.30<br />

172<br />

172<br />

.• 69<br />

...•••. 62<br />

. •.••..• 62<br />

•.• 89<br />

28]<br />

233<br />

283<br />

211<br />

.38<br />

.69<br />

.25<br />

si:dcfsyscaU • • • • • • • • • • • • • • • •<br />

si:dctcrmine-and -s<strong>et</strong>-tennin<strong>al</strong>-type •<br />

si:enablc-vms-c<strong>al</strong>l -trampoline<br />

si:enter-readtable. • •<br />

si:finish-p<strong>al</strong>ch • • •<br />

si:gct-ca11-m<strong>et</strong>ers ••••<br />

si:g<strong>et</strong>-system-version • •<br />

si:gct -syslem-version-list<br />

si:gctjpi-string •<br />

si:gctjpi-v<strong>al</strong>ue • • • • • • •<br />

si:gctsyi-string. •<br />

si:gcL~yi-v<strong>al</strong>ue .•<br />

si:had-vms-objcct-fiJc •<br />

si:initiaIi7c-patch-systcm •<br />

si:locate-S}mbol-tablc-v<strong>al</strong>ue •<br />

si:lookup-rcadtable. • • • •<br />

~IR<br />

218<br />

279<br />

.56<br />

109<br />

••• 39<br />

232<br />

225<br />

242<br />

242<br />

283<br />

219<br />

219<br />

219<br />

219<br />

283<br />

219<br />

221<br />

283<br />

283<br />

300<br />

299<br />

298<br />

211<br />

299<br />

219<br />

283<br />

225<br />

282<br />

282<br />

242<br />

241<br />

242<br />

242<br />

299<br />

2.84<br />

300<br />

218<br />

23-DEC-83


<strong>NIL</strong> Manu<strong>al</strong><br />

321 Function, Macro, and Speci<strong>al</strong> Form Index<br />

si:loor-genlemp ...<br />

si: lool'-n;ullcd-\'ariablc<br />

si:loop-tassoc •<br />

si:loor-tequ<strong>al</strong> •<br />

si:loop-uncmbcr .<br />

si:make- fab . .<br />

si:makc-nam.<br />

si:make-rab .<br />

si:make-xab. .<br />

si:modulc·sourcc-file<br />

si:ncw-p<strong>al</strong>ch-s),slcm<br />

si:uolc-rrimili\ c- fOIll .<br />

si:r:1ckagc-!'~ mholconc.<br />

....<br />

si:ragcl~lUlt-rount.<br />

si:rrinr-t.cr<strong>al</strong>d . . .<br />

si:rc-cdil-r:1lch ..<br />

si:rcqllirc-charactcr . .<br />

si:rcquirc-characlcr-{hnuIn.<br />

si:mlsSciosc . .<br />

si:nllsSconncct .<br />

si:nnsScreatc. •<br />

si:nnsSdcJctc.<br />

si:rmsSdisconncct .<br />

si:rrn~Sdisplay .<br />

si:nnsScnter. •<br />

si:rmsSerasc •<br />

si:rmsScx tend<br />

c;i'rmc;~finn<br />

si:mlsSflush<br />

si:mlsSfrcc.<br />

si: mls$g<strong>et</strong> .<br />

si:rrnsSnxt\'ol. .<br />

si: nnsSopcn . •<br />

si: rmsSparse •<br />

si:nnsSput. • •<br />

si:nns$rcad . .<br />

si:nnsSrelease • • • • •<br />

si:rmsSremove •<br />

si:rmsSrename •<br />

si:nnsSrewind<br />

si:rmsSscarch. •<br />

si:rmsSs<strong>et</strong>ddir<br />

si: rmsSspace. •<br />

si:rmsStrunc. •<br />

si: rms$update<br />

si:rms$wait • •<br />

si:rmsSwJite •<br />

si:sel-patch-environmcnl.<br />

si:sct-systcm-status. .<br />

si:show-c<strong>al</strong>l-mcters. •<br />

si:subtract -c<strong>al</strong>l-m<strong>et</strong>ers .<br />

si:systcm-vemon-info.<br />

si:trnlog. • • • • • •<br />

si:updatc-systcm -statuses?<br />

sign<strong>al</strong> ••<br />

signum.<br />

signum&<br />

]66<br />

16b<br />

166<br />

166<br />

166<br />

207<br />

207<br />

207<br />

· 207<br />

221<br />

284<br />

101<br />

.70<br />

224<br />

282<br />

· 283<br />

.97<br />

. 97<br />

208<br />

208<br />

208<br />

208<br />

208<br />

· • 208<br />

209<br />

208<br />

208<br />

2(\8<br />

208<br />

... 208<br />

208<br />

• . 208<br />

208<br />

209<br />

••• 208<br />

• • 209<br />

208<br />

209<br />

· 209<br />

208<br />

209<br />

209<br />

209<br />

• • 209<br />

209<br />

209<br />

209<br />

283<br />

283<br />

225<br />

225<br />

282<br />

209<br />

282<br />

229<br />

.77<br />

.88<br />

simp.<br />

simpand ••<br />

simpandlist<br />

simplc-hit-vector-Icngth<br />

simple-gener<strong>al</strong> - vcctor-Iength<br />

simplc-vector-Iength<br />

simpnot ..<br />

simpor .•<br />

simporlist.<br />

sin<br />

sinh.<br />

sixth.<br />

somc.<br />

son .<br />

sonC3r .<br />

utils:source- need -COnlrilc?<br />

sqrt •••<br />

s..\tatus ..... .<br />

stablc"son ~ . . •<br />

st:mdard-char-p .<br />

status ••••<br />

Sle\c:argumcnt? • •<br />

slc\'c:huffcr. . • •<br />

slcYc:buffcr-begin? •<br />

stcvc:huffcr-cnd? • • • . •<br />

stevc:c-u-only? • .<br />

stcvc:cd-Iosc ..<br />

stc\c:ed-waming.. .<br />

Slc\c:cditor-bind-kcy.<br />

stc\,c:edilor-dcfun-key •<br />

stevc: first -line?<br />

slc\c:lasl-linc? ••<br />

stcvc:linc-ncxt. • •<br />

steve:Jine-previous .<br />

steve:makc-bp. . • .<br />

stevc:make-line • • •<br />

steve:makc-scrcen -image<br />

ste"c:mx" prompter. •<br />

stc\'c:not-buffer-begin<br />

steve: not -buffer-end •<br />

steve: not - first -line •<br />

stcve:not-last-line ••<br />

Sleve:nth-next-line. •<br />

stevc:nth-previous-line •<br />

stevc:overwritc-done.<br />

steve:overwJite-home •<br />

stcvc:overwnte-start •<br />

stevc:overwritc-tcrpJi. •<br />

steve:point • • • • •<br />

Slevc:point -selectcd. •<br />

stc"e:rcad-huffcr-name •<br />

stevc:rcad-file-name<br />

stcvc:rc<strong>al</strong>-arg-sup? •<br />

stcvc:sa,c-<strong>al</strong>l-filt.'S •<br />

stcvc:sclcct-point. •<br />

stcve:sclcct-point-in-currcnt-window<br />

.295<br />

.295<br />

.295<br />

· .110<br />

.109<br />

.109<br />

.295<br />

.295<br />

· .295<br />

77<br />

• 78<br />

50<br />

54<br />

55<br />

55<br />

.127<br />

76<br />

87<br />

55<br />

94<br />

87.224<br />

.278<br />

.276<br />

.278<br />

.278<br />

.278<br />

.277<br />

.~T?<br />

.278<br />

.274<br />

.275<br />

.278<br />

.278<br />

.276<br />

.276<br />

.275<br />

.276<br />

.279<br />

.279<br />

• .278<br />

.278<br />

.278<br />

. .•. 278<br />

.276<br />

.276<br />

.279<br />

.279<br />

.279<br />

.279<br />

.276<br />

.276<br />

.279<br />

.279<br />

.278<br />

• •• 277<br />

.276<br />

.276<br />

23-DEC-83


Function, Macro. and Speci<strong>al</strong> Fonn Index<br />

322 <strong>NIL</strong> Manu<strong>al</strong><br />

stc"e:sctup-modc-arca. •<br />

Slc\c:with-no-pass<strong>al</strong>i<br />

streamJl. • .<br />

siring . . . .<br />

string-apJlend<br />

slring-char-p.<br />

siring-downca!>c.<br />

siring-equ<strong>al</strong> • • •<br />

!.lring-equ<strong>al</strong>-hash .<br />

string-greate", . .<br />

siring-left-trim ..<br />

siring-kngth .. .<br />

slring-lcssl1 ... .<br />

sliing-lIol-(.'qu<strong>al</strong><br />

siring-JHlI-grcatcrp<br />

stnng-nol-Icssp. •<br />

Slring-nre\ers~ . •<br />

slrillg-re\ erse. . .<br />

slli IIg - re\ crsc-sea rch . .<br />

string - n?\ l'rsc-Sl':Jrch-char<br />

st ring -rc\crsc-scarch" not -char<br />

slring-rc\crsc-scarch-not-SCI •<br />

slJing-re\'crsc-search-s<strong>et</strong> .•<br />

st ring - right - trim •<br />

string-search. • • ••<br />

string-!iCarch-char. • • • • • • • •<br />

string-scarch-nol-char.<br />

!ilring-'I('arrh"nnr-~t<br />

string-search-sct<br />

siring-Irim. •<br />

!lolring"upC3:ie •<br />

string/: .<br />

siring( .•<br />

Slring = •<br />

Slringp<br />

subl •<br />

sublis. •<br />

subseq.<br />

subsctp<br />

subst •<br />

substitute<br />

substitute-if •<br />

substitute-if - not<br />

substring. • • •• •• • • • •<br />

si:suhlract-c<strong>al</strong>l-m<strong>et</strong>ers • •<br />

subtypep.<br />

svref ••••••<br />

sxhash ••..••<br />

sys:sxhash-combine •<br />

symbol- function<br />

S} mbol-Jlame • • •<br />

!\ymhol-paciage.<br />

symbol-pliSl ••<br />

• • 279<br />

• • 278<br />

• 179<br />

• • 112<br />

• 115<br />

• • }9<br />

• •• JJ4<br />

• • • • 113<br />

• • 119<br />

•.•• 113<br />

• 115<br />

• 114<br />

•••• 113<br />

• •• 113<br />

• 113<br />

· .• ID<br />

• • • • • 115<br />

• • • • • 115<br />

)]6<br />

• • • • 116<br />

• 116<br />

• • 116<br />

••• 116<br />

• US<br />

• 116<br />

• • 116<br />

• • 116<br />

111\<br />

• • • J 16<br />

• 115<br />

• 114<br />

• • 113<br />

• 113<br />

• 113<br />

• 113<br />

• • 119<br />

• • 114<br />

• 113<br />

19<br />

75<br />

• • • • • 60<br />

••••• SO<br />

62<br />

60<br />

53<br />

• • • • • 54<br />

54<br />

• 115<br />

.225<br />

• 18<br />

• 109<br />

• 119<br />

• • 119<br />

68<br />

66<br />

• • • • • 67<br />

6S<br />

symhol - \'<strong>al</strong>uc<br />

symholconc •<br />

symbolp ••<br />

symcvaJ .••<br />

!l)'s:%fixnum-ash-with-m·crflow-trapping.<br />

!\ys:%fixnum- differencc-with -overflow-lraJlJling • .<br />

sys:%fix num -plus-with-overflow-trapping .<br />

sys;%fixnum-limcs-with-ovcrflow-trapping •<br />

s),s:sxhash-combinc •••<br />

· .68<br />

· .70<br />

• • 18<br />

.69<br />

.90 .<br />

· .90<br />

· .90<br />

• .90<br />

119<br />

si:syslcm-vcrsion-info. • 282<br />

taghod) .<br />

tailp •<br />

lan ••<br />

tanh.<br />

tenUl •<br />

tcrpri •<br />

thc ••<br />

third.<br />

Jhrow.<br />

time.<br />

. ....... .<br />

.......<br />

timc:comcn-\·ms-Lime-to-uni\crs<strong>al</strong>-timc.<br />

limc:da)-of-the-wcck. • • • • •<br />

timc:day"of-the-wcci-string.<br />

timc:daylight-savings-p • • •<br />

time: daylight -s<strong>al</strong>ings-time-p •<br />

time: last -sunday-in-april • •<br />

'imp'I~~f-Qlnrt~y-in-n("tn~r<br />

timc:lcap·ycar-p. • • • • •<br />

limc:modc-languagc-fctch •<br />

timc:month -length<br />

timc:monLh-string • • • • •<br />

limc:moonJ'hasc . • • • • •<br />

time:prim-bricf-univcrs<strong>al</strong>-time • •<br />

time:print-current-date • • • •<br />

timc:print -current-mail-fonnat.. date.<br />

time:print -currenr-moonphase<br />

time:print-current-time •<br />

time:print - date. • • •<br />

timc:prinl-moonphase ••<br />

• •• 34<br />

• .5Q<br />

••••••• 77<br />

•••••• 78<br />

• •• 56<br />

185<br />

.47<br />

• •• 56<br />

• •• 30<br />

223<br />

• 240<br />

238<br />

237<br />

238<br />

238<br />

239<br />

~3Q<br />

. 238<br />

237<br />

238<br />

. 237<br />

238<br />

••••• 236<br />

236<br />

•• 236<br />

239<br />

235<br />

236<br />

239<br />

timc:print-time. • • • • . . . . . . 23S<br />

time: pri nt ·univers<strong>al</strong>-date ••••• 236<br />

time:print-univcrs<strong>al</strong>-maiJ-(onnat-d<strong>al</strong>e. •<br />

236<br />

time:print-univers<strong>al</strong>-time • • • • • • •<br />

235<br />

timc:rcgular-american - da)·Jjg.ht -savings-time-p • 239<br />

time:timezone-string • • • • •<br />

238<br />

time:verify-date<br />

238<br />

time:zoneconv •<br />

• • • • • 239<br />

timer. • • • ••<br />

223<br />

times. • • • •<br />

. . ~ .75<br />

time:timezone-suing<br />

238<br />

to-SIring •<br />

112<br />

trace •••<br />

179,220<br />

si:tmlog ••<br />

209<br />

truncate ••<br />

• •• 79<br />

typcca.~ ••<br />

• •• 30<br />

typep. •<br />

.18


N II. Manu<strong>al</strong><br />

323 Fum:tion. Macro. and Speci<strong>al</strong> F0n11 Index<br />

union.<br />

unless.<br />

unread-char.<br />

unwind-protcct.<br />

si:updatc-systcm -statuscs? .<br />

uppcr-case-p . . • • .<br />

uscr-homcdir-p<strong>al</strong>hnamc .<br />

uscr-scr3tchdir-pathnamc<br />

lIscr-workingdir-p<strong>al</strong>hnamc .<br />

1I1ils:pp-into-lilc. • . . .<br />

1I1ils:print-illI0-lilc .•..<br />

1IIils:sourcl'-nl'cd-compilc? .<br />

utils:\a~-sourrc-lilc ..•.<br />

utib.:\a~-s()urcc-nccds-rccompilc? .<br />

\<strong>al</strong>rel .. .<br />

vailies .. .<br />

\<strong>al</strong>ucs-list.<br />

\'<strong>al</strong>ucs-\ ector.<br />

ulils:vas-sourcc-Iilc .<br />

utils:\:ls-sollrcc-nccds-rccompilc? .<br />

\CClor •••••<br />

vcctor-lcngth<br />

vcctor-pop . •<br />

vcctor-push .<br />

vcctor-push-extend •<br />

\,C'rforp ....<br />

\cri(v. . . . • .<br />

timc:\crify-datc<br />

vref ••<br />

.62<br />

.29<br />

184<br />

.36<br />

282<br />

.95<br />

199<br />

• 200<br />

200<br />

228<br />

228<br />

• 227<br />

227<br />

227<br />

289<br />

.36<br />

.37<br />

.37<br />

227<br />

227<br />

· 109<br />

108<br />

106<br />

106<br />

106<br />

lQ<br />

228<br />

· 2J8<br />

108<br />

when •.<br />

whercis •<br />

who-c<strong>al</strong>ls.<br />

with-input - from -string<br />

stcl'c:with-no-passaU •<br />

with-oJ;>en-file. • . •<br />

with-output-to-string •<br />

writc-bits. •<br />

write-byte. .<br />

write-char.<br />

write-line.<br />

write-string •<br />

loons •••<br />

y-or-n-p ••<br />

yes-or-no-p. .<br />

zerop. • • ••<br />

time:loneconv • •<br />

\&.<br />

.28<br />

221<br />

221<br />

182<br />

• 278<br />

181<br />

182,<br />

186<br />

•••••••• 186<br />

185<br />

· 185<br />

185<br />

.57<br />

197<br />

• • 197<br />

.73<br />

239<br />

.88<br />

.91<br />

87.88<br />

23-DEC-83

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!