Annotation of 43BSDTahoe/ucb/lisp/doc/ch9.n, revision 1.1

1.1     ! root        1: .\" Copyright (c) 1980 Regents of the University of California.
        !             2: .\" All rights reserved.  The Berkeley software License Agreement
        !             3: .\" specifies the terms and conditions for redistribution.
        !             4: .\"
        !             5: .\"    @(#)ch9.n       6.2 (Berkeley) 5/14/86
        !             6: .\"
        !             7: ." $Header: ch9.n 1.4 83/07/21 21:08:57 sklower Exp $
        !             8: .Lc Arrays\ and\ Vectors 9
        !             9: .pp
        !            10: Arrays and vectors are two means of expressing aggregate
        !            11: data objects in
        !            12: .Fr .
        !            13: Vectors may be thought of as sequences of data.
        !            14: They are intended as a vehicle for user-defined
        !            15: data types.
        !            16: This use of vectors is still experimental and subject
        !            17: to revision.
        !            18: As a simple data structure, they are similar to
        !            19: hunks and strings.
        !            20: Vectors are used to implement closures,
        !            21: and are useful to communicate with foreign functions.
        !            22: Both of these topics were discussed in Chapter 8.
        !            23: Later in this chapter,
        !            24: we describe the current implementation of vectors, and will
        !            25: advise the user what is most likely to change.
        !            26: .pp
        !            27: Arrays in 
        !            28: .Fr
        !            29: provide a programmable data structure access mechanism.
        !            30: One possible use for 
        !            31: .Fr
        !            32: arrays is to implement Maclisp style arrays which are simple vectors
        !            33: of fixnums, flonums or general lisp values.
        !            34: This is described in more detail in \(sc9.3 but first
        !            35: we will describe how array references are handled by
        !            36: the lisp system.
        !            37: .pp
        !            38: The structure of an array object is given in \(sc1.3.10 and reproduced here
        !            39: for your convenience.
        !            40: .(b
        !            41: .TS
        !            42: box center ;
        !            43: c | c | c | c .
        !            44: Subpart name   Get value       Set value       Type
        !            45: 
        !            46: =
        !            47: access function        getaccess       putaccess       binary, list
        !            48:                        or symbol
        !            49: _
        !            50: auxiliary      getaux  putaux  lispval
        !            51: _
        !            52: data   arrayref        replace block of contiguous
        !            53:                set     lispval
        !            54: _
        !            55: length getlength       putlength       fixnum
        !            56: _
        !            57: delta  getdelta        putdelta        fixnum
        !            58: .TE
        !            59: .)b
        !            60: .sh 2 "general arrays" \n(ch 1
        !            61: Suppose the evaluator is told to evaluate \fI(foo\ a\ b)\fP
        !            62: and the function cell of the symbol foo contains an array object
        !            63: (which we will call foo_arr_obj).
        !            64: First the evaluator will evaluate and stack the values of 
        !            65: .i a 
        !            66: and 
        !            67: .i b .
        !            68: Next it will stack the array object foo_arr_obj.
        !            69: Finally it will call the access function of foo_arr_obj.
        !            70: The access function should be a lexpr\*[\(dg\*]
        !            71: or a symbol whose 
        !            72: function cell contains a lexpr.
        !            73: .(f
        !            74: \*[\(dg\*]A lexpr is a function which accepts any number of arguments
        !            75: which are evaluated before the function is called.
        !            76: .)f
        !            77: The access function is responsible for locating and returning 
        !            78: a value from the array.
        !            79: The array access function is free to interpret the arguments as it wishes.
        !            80: The Maclisp compatible array access function which is provided 
        !            81: in the standard
        !            82: .Fr
        !            83: system interprets the arguments as subscripts in the same way as 
        !            84: languages like Fortran and Pascal.
        !            85: .pp
        !            86: The array access function will also be called upon to store elements in 
        !            87: the array.
        !            88: For example, \fI(store\ (foo\ a\ b)\ c)\fP
        !            89: will automatically expand to (foo c a b) and when the evaluator is called
        !            90: to evaluate this, it will evaluate the arguments 
        !            91: .i c , 
        !            92: .i b 
        !            93: and
        !            94: .i a .
        !            95: Then it will
        !            96: stack the array object (which is stored 
        !            97: in the function cell of foo) and call the array access function
        !            98: with (now) four arguments.
        !            99: The array access function must be able to tell this is a store operation,
        !           100: which it can do by checking the number of arguments it has been
        !           101: given (a lexpr can do this very easily).
        !           102: .sh 2 "subparts of an array object"
        !           103: An array is created by allocating an
        !           104: array object with
        !           105: .i marray
        !           106: and  filling in the fields.
        !           107: Certain lisp functions interpret the values of the subparts 
        !           108: of the array object in special
        !           109: ways as described in the following text.
        !           110: Placing illegal values in these subparts may cause
        !           111: the lisp system to fail.
        !           112: .sh 3 "access function"
        !           113: The purpose of the access function has been described above.
        !           114: The contents of the access function should be a lexpr, 
        !           115: either a binary (compiled function) or a list (interpreted function).
        !           116: It may also be a symbol whose function cell contains a function 
        !           117: definition.
        !           118: This subpart 
        !           119: is used by 
        !           120: .i eval , 
        !           121: .i funcall , 
        !           122: and 
        !           123: .i apply
        !           124: when evaluating array references.
        !           125: .sh 3 auxiliary
        !           126: This can be used for any purpose. If it is a list and the first element
        !           127: of that list is the symbol unmarked_array then the data subpart will
        !           128: not be marked by the garbage collector (this is used in the Maclisp
        !           129: compatible array package and has the potential for causing strange errors
        !           130: if used incorrectly).
        !           131: .sh 3 data
        !           132: This is either nil or points to a block of data space allocated by 
        !           133: .i segment 
        !           134: or 
        !           135: .i small-segment.
        !           136: .sh 3 length
        !           137: This is a fixnum whose value is the number of elements in the
        !           138: data block.  This is used by the garbage collector and by 
        !           139: .i arrayref
        !           140: to determine if your index is in bounds.
        !           141: .sh 3 delta
        !           142: This is a fixnum whose value is the number of bytes in each element of 
        !           143: the data block.
        !           144: This will be four for an array of fixnums or value cells, and eight
        !           145: for an array of flonums.
        !           146: This is used by the garbage collector and 
        !           147: .i arrayref
        !           148: as well.
        !           149: .sh 2 "The Maclisp compatible array package"
        !           150: .pp
        !           151: A Maclisp style array is similar to what is known as arrays in other
        !           152: languages: a block of homogeneous data elements which
        !           153: is indexed by one or more integers called subscripts.
        !           154: The data elements can be all fixnums, flonums or general lisp objects.
        !           155: An array is created by a call to the function 
        !           156: .i array 
        !           157: or \fI*array\fP.
        !           158: The only difference is that 
        !           159: .i *array
        !           160: evaluates its arguments.
        !           161: This call: 
        !           162: .i "(array foo t 3 5)"
        !           163: sets up an array called foo of dimensions 3 by 5.
        !           164: The subscripts are zero based. 
        !           165: The first element is \fI(foo\ 0\ 0)\fP, the next is \fI(foo\ 0\ 1)\fP
        !           166: and so on up to \fI(foo\ 2\ 4)\fP.
        !           167: The t indicates a general lisp object array which means each element of
        !           168: foo can be any type.
        !           169: Each element can be any type since all that is stored in the array is
        !           170: a pointer to a lisp object, not the object itself.
        !           171: .i Array 
        !           172: does this by allocating an array object
        !           173: with
        !           174: .i marray
        !           175: and then allocating a segment of 15 consecutive value cells with
        !           176: .i small-segment
        !           177: and storing a pointer to that segment in the data subpart of the array
        !           178: object.
        !           179: The length and delta subpart of the array object are filled in (with 15
        !           180: and 4 respectively) and the access function subpart is set to point to 
        !           181: the appropriate  array access function.
        !           182: In this case there is a special access function for two dimensional
        !           183: value cell arrays called arrac-twoD, and this access function is used.
        !           184: The auxiliary subpart is set to (t\ 3\ 5) which describes the type of array
        !           185: and the bounds of the subscripts.  
        !           186: Finally this array object is placed in the function cell of the symbol foo.
        !           187: Now when 
        !           188: .i "(foo 1 3)"
        !           189: is evaluated, the array access function is invoked with three arguments:
        !           190: 1, 3 and the array object.  From the auxiliary field of the
        !           191: array object it gets a description of the particular array.
        !           192: It then determines which element \fI(foo\ 1\ 3)\fP refers to  and 
        !           193: uses arrayref to extract that element.
        !           194: Since this is an array of value cells, what arrayref returns is a
        !           195: value cell whose value is what we want, so we evaluate the value cell
        !           196: and return it as the value of \fI(foo\ 1\ 3)\fP.
        !           197: .pp
        !           198: In Maclisp the call \fI(array\ foo\ fixnum\ 25)\fP
        !           199: returns an array whose data object is a block of 25 memory words.
        !           200: When fixnums are stored in this array, the actual numbers are 
        !           201: stored instead of pointers to the numbers as is done in general lisp
        !           202: object arrays.
        !           203: This is efficient under Maclisp but inefficient in
        !           204: .Fr
        !           205: since every time a value was referenced from an array it had to be copied
        !           206: and a pointer to the copy returned to prevent aliasing\*[\(dg\*].
        !           207: .(f
        !           208: \*[\(dg\*]Aliasing is when two variables are share the same storage location.
        !           209: For example if the copying mentioned weren't done then after 
        !           210: \fI(setq\ x\ (foo\ 2))\fP was done, the value of x and 
        !           211: (foo\ 2) would share the same 
        !           212: location.
        !           213: Then should the value of (foo\ 2) change, x's value would change as well.
        !           214: This is considered dangerous and as a result pointers are never returned
        !           215: into the data space of arrays.
        !           216: .)f
        !           217: Thus t, fixnum and flonum arrays are all implemented in the same 
        !           218: manner.
        !           219: This should not affect the compatibility of Maclisp
        !           220: and 
        !           221: .Fr .
        !           222: If there is an application where a block of fixnums or flonums is required,
        !           223: then the exact same effect of fixnum and flonum arrays in Maclisp
        !           224: can be achieved by using fixnum-block and flonum-block arrays.
        !           225: Such arrays are required if you want to pass a large number of arguments to a 
        !           226: Fortran or C coded function and then get answers back.
        !           227: .pp
        !           228: The Maclisp compatible array package is 
        !           229: just one example of how a general array scheme can be implemented.
        !           230: Another type of array you could implement would be hashed arrays.
        !           231: The subscript could be anything, not just a number.
        !           232: The access function would hash the subscript and use the result to
        !           233: select an array element.
        !           234: With the generality of arrays also comes extra cost; if you just
        !           235: want a simple aggregate of (less than 128) general lisp objects
        !           236: you would be wise to look into using hunks.
        !           237: .sh 2 vectors
        !           238: Vectors were invented to fix two shortcommings with hunks.
        !           239: They can be longer than 128 elements.  They also have a
        !           240: tag associated with them, which is intended to say, for example,
        !           241: "Think of me as an \fIBlobit\fP."  Thus a \fBvector\fP
        !           242: is an arbitrary sized hunk with a property list.
        !           243: .pp
        !           244: Continuing the example,
        !           245: the lisp kernel may not know how to print out
        !           246: or evaluate \fIblobits\fP, but this is information which will
        !           247: be common to all \fIblobits\fP.  On the other hand, for each
        !           248: individual blobits there are particulars which are likely to change,
        !           249: (height, weight, eye-color).  This is the part that would
        !           250: previously have been stored in the individual entries in the hunk,
        !           251: and are stored in the data slots of the vector.
        !           252: Once again we summarize the structure of a vector in tabular form:
        !           253: .(b
        !           254: .TS
        !           255: box center ;
        !           256: c | c | c | c .
        !           257: Subpart name   Get value       Set value       Type
        !           258: 
        !           259: =
        !           260: datum[\fIi\fP] vref    vset    lispval
        !           261: _
        !           262: property       vprop   vsetprop        lispval
        !           263:                vputprop
        !           264: _
        !           265: size   vsize   \-      fixnum
        !           266: .TE
        !           267: .)b
        !           268: Vectors are created specifying size and optional fill value using the
        !           269: function (\fInew-vector\fP  'x_size ['g_fill ['g_prop]]), or by
        !           270: initial values: (\fIvector\fP ['g_val ...]).
        !           271: .sh 2 "anatomy of vectors"
        !           272: There are some technical details about vectors, that the user should
        !           273: know:
        !           274: .sh 3 size
        !           275: The user is not free to alter this.  It is noted when the vector
        !           276: is created, and is used by the garbage collector.  The garbage
        !           277: collector will coallesce two free vectors, which are neighbors
        !           278: in the heap.  Internally, this is kept as the number of bytes
        !           279: of data.  Thus, a vector created by (\fIvector\fP 'foo), has a
        !           280: size of 4.
        !           281: .sh 3 property
        !           282: Currently, we expect the property to be either a symbol, or a list
        !           283: whose first entry is a symbol.  The symbols \fBfclosure\fP and
        !           284: \fBstructure-value-argument\fP are magic, and their effect is described in
        !           285: Chapter 8.  If the property is a (non-null) symbol, the vector
        !           286: will be printed out as <symbol>[<size>].  
        !           287: Another case is if the property is actually a (disembodied) property-list, which
        !           288: contains a value for the indicator \fBprint\fP.
        !           289: The value is taken to be a Lisp function, which the printer
        !           290: will invoke with two arguments:  the vector and the current output port.
        !           291: Otherwise, the vector will be printed as vector[<size>].
        !           292: We have vague (as yet unimplemented) ideas
        !           293: about similar mechanisms for evaluation properties.
        !           294: Users are cautioned against putting anything other than nil
        !           295: in the property entry of a vector.
        !           296: .sh 3 "internal order"
        !           297: In memory, vectors start with a longword containing the size
        !           298: (which is immediate data within the vector).
        !           299: The next cell contains a pointer to the property.
        !           300: Any remaining cells (if any) are for data.
        !           301: Vectors are handled differently from any other object in
        !           302: .Fr,
        !           303: in that a pointer to a vector is pointer to the first data
        !           304: cell, i.e. a pointer to the \fIthird\fP longword of the structure.
        !           305: This was done for efficiency in compiled code and for uniformity
        !           306: in referencing immediate-vectors (described below).
        !           307: The user should never return a pointer to any other part
        !           308: of a vector, as this may cause the garbage collector to follow an
        !           309: invalid pointer.
        !           310: .sh 2 "immediate-vectors"
        !           311: Immediate-vectors are similar to vectors.  They differ, in
        !           312: that binary data are stored in space directly within the vector.
        !           313: Thus the garbage collector will preserve the vector itself (if used),
        !           314: and will only traverse the property cell.
        !           315: The data may be referenced as longwords, shortwords, or even bytes.
        !           316: Shorts and bytes are returned sign-extended.
        !           317: The compiler open-codes such references,
        !           318: and will avoid boxing the resulting integer data, where possible.
        !           319: Thus, immediate vectors may be used for efficiently processing
        !           320: character data.
        !           321: They are also useful in storing results from functions written
        !           322: in other languages.
        !           323: .(b
        !           324: .TS
        !           325: box center ;
        !           326: c | c | c | c .
        !           327: Subpart name   Get value       Set value       Type
        !           328: 
        !           329: =
        !           330: datum[\fIi\fP] vrefi-byte      vseti-byte      fixnum
        !           331:        vrefi-word      vseti-word      fixnum
        !           332:        vrefi-long      vseti-long      fixnum
        !           333: _
        !           334: property       vprop   vsetprop        lispval
        !           335:                vputprop
        !           336: _
        !           337: size   vsize   \-      fixnum
        !           338:        vsize-byte              fixnum
        !           339:        vsize-word              fixnum
        !           340: .TE
        !           341: .)b
        !           342: To create immediate vectors specifying size and fill data,
        !           343: you can use the functions
        !           344: \fInew-vectori-byte\fP,
        !           345: \fInew-vectori-word\fP,
        !           346: or \fInew-vectori-long\fP.
        !           347: You can also use the functions
        !           348: \fIvectori-byte\fP,
        !           349: \fIvectori-word\fP,
        !           350: or \fIvectori-long\fP.
        !           351: All of these functions are described in
        !           352: chapter 2.

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.