==================================================== ==== Guidelines for APL Libraries ==== ==================================================== This document exists in 2 versions: this version (which is supposed to be useful for all kinds of APL interpreters) and Library-Guidelines-GNU-APL.html which contains additional information that is only relevant for users of GNU APL. A section may be empty if the other version of this document contains only information relevant for GNU APL. 0. Terminology ============== The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [RFC2119]. 1. Libraries ============ For the purpose of this document, a library shall be code in any language (but primarily APL and C/C++) that is made available by individual developers to a larger community. This document states requirements on such libraries in order to make them useful and usable. Different requirements may be in conflict, and then the following order (in decreasing relevance) shall be applied to resolve that, but in a pragmatic way: A. User friendliness and usability B. Portability C. Clear Code structure D. Performance ... 1.1 Intended audience --------------------- APL programmers. 1.2 How Libraries may be used ----------------------------- The standard way of using a library of APL code SHALL BE a simple single command such as: )COPY lib However, the same library could be used in completely different ways as well: - published on a web page - cut-and-paste (xterm middle mouse button, or CTRL-C / CTRL-V) between windows or browsers The file format MUST support all use cases above. This rules out file formats that use non-portable encodings. 1.3 Library structure at APL Level ---------------------------------- An APL script file consists of several lines of APL code that is executed line-by-line when )LOADed or )COPYd. An APL library uses the same format but should have a particular structure in order to be useful as a library: A. )COPY of other libraries B. Definition of APL functions C. Initialization of global variables A APL script file often has the same order, but may then call one or more of the defined functions, and possibly )OFF at the and of the script. This SHOULD be avoided in libraries because it could bring the workspace into a state that is not foreseen by other libraries. What is acceptable after C. is the execution of functions that check the )COPYd libraries (dependencies, version numbers, etc,). Such check functions MUST NOT, however print anything, except when errors are detected. This is because a library may be )COPYd several times 1.4 Portability --------------- We foresee 3 levels of portability for libraries that contain APL code: L1: ISO portability. This means that the APL uses only APL constructs and commands defined in the ISO standard or are present (and identical) in all major APL interpreters. L2: basic portability: This means that non-standard functions can be used in APL code but only via wrapper functions in another library called 'base'. Portability is achieved by only porting the 'base' library to another interpreter and then all libraries with basic portability will run on that interpreter. This more or less means that all non-standard ⎕-functions are wrapped, e.g. ⎕CR becomes ∆CR, etc. L3: Interpreter specific portability: These libraries can only be used with APL interpreters of the same vendor because they heavily use extensions of the ISO standard or because they are used to implement missing functions in the interpreter of that vendor. 1.4.1 The base library ---------------------- The 'base' library is a L3 library that is created as a means to simplify the use of the same L2 library on otherwise incompatible APL systems. The typical difference between such systems is the number of ⎕-functions and, less often, between ⎕-variables. The idea is that instead of using a non-portable ⎕-function say ⎕XYZ in the library, one would use ∆XYZ and define ∆XYZ in the base library. Porting the base library once to a different APL interpreter would then cause all L2 libraries to function unmodified on the new interpreter. The base library MUST define wrapper functions for all ⎕-functions and ⎕-variables that differ from the corresponding functions in the ISO standard. Such ⎕-functions are either completely new, or extend existing ⎕-functions (additional arguments, dyadic ⎕-function in the interpreter vs. monadic ⎕-function in the standard etc. The base library MAY define wrapper functions even if no differences exist; this is for handling cases where it is not clear if some behavior is standard or not. In these cases the designer of the library shall decide whether the wrapper or the original function is used. The names of ⎕-functions are usually case insensitive while user defined functions are not. This is used in the following name convention for wrapper functions: The wrapper function for a ⎕-function, say ⎕FUN, shall be ∆FUN (and not base∆FUN as for other libraries. This is to make changing the names simple. A ⎕-variable, say ⎕VAR, has two wrapper functions ∆VAR and ∆var. The uppercase variant is a niladic function for referencing ⎕VAR while the lowercase variant is a monadic function setting ⎕VAR. Uppercase was chosen because it is the form used historically and in the ISO standard. Read-only system variables only have the ∆VAR wrapper function. Another library foreseen is a 'meta' library that contains functions related to library managements (dependencies, revision numbers, copyrights etc). 'meta' is a L2 library (and as such must not )COPY a L3 library). Generally speaking, a L1 library must not depend on a L2 or L3 library and a L2 library must not depend on a L3 library. The base library SHOULD be maintained by the vendor of the target APL interpreter or by users of that interpreter. 1.4.2 The meta library ---------------------- A library MUST contain a certain amount of meta information in order to be used by e.g. packet managers. For the developer of a library this SHALL NOT create too much burden. Therefore a meta library shall be developed that reduces the extra work of the developer to the bare minimum, such as providing contact information, bug report email, and licenses. The meta library shall be a L1 library (i.e. full portability) and it shall also contain functions that check if all meta information needed is in a library. A library, say FOO, shall contain a niladic function FOO⍙metadata that returns meta information (see 2.2 below for an explanation). For example: SQL⍙metadata Author Elias Mårtenson BugEmail bug-apl@gnu.org Documentation Download https://github.com/lokedhs/apl-sqlite License LGPL Portability L3 Provides SQL Requires Version 1.0 The result of FOO⍙metadata is a nested N by 2 matrix of property names and values. Property names and values shall be simple text strings. The FOO⍙metadata function is used by package managers to extract information about the library. A library called meta may be provided that contains functions for checking meta information and for preparing it in different formats such as HTML for listing libraries, packet managers, and other programs. A library need not )COPY the meta library itself; the meta library is intended to be used by programs like package managers and for web pages listing packages and their properties. The details need to be worked out... 1.5 Library types ----------------- We expect the following kinds of code: A. pure APL libraries B. mixed APL/C/C++ (and possibly other languages). In A. the focus is on APL and this will most likely be a L2 or L1 library. In B. the APL code will be a thin wrapper level. This will be a typical L2 lib. 2. Naming Conventions ===================== The library concept described in this documents uses a number of naming conventions as follows. 2.1 Library name ---------------- The library name SHALL be short, but still long enough to be easily remembered by the user. For example: SQL for the SQL interface FIO for the FILE_IO functions FOO for an example library used in the following. ... 2.2 APL names ------------- In APL the functions and global variables of library 'foo' shall be named foo∆function_name or foo∆variable_name. Local variables, function arguments, and return values SHALL have the usual short names without the foo∆ prefix. A second prefix foo⍙ is used for functions related to meta information. These meta functions are not used by library user but by the management of libraries as explained further down. 2.3 Library Filename -------------------- The APL code for library foo MUST be contained in a file called foo.apl. 2.4 Library Directories ----------------------- Libraries can live in one of 10 directories that are selected by a 'library reference number' from 1-9, and a missing library number means 0. The library reference number is an optional argument of the )LOAD, )COPY and )SAVE commands like: )COPY 4 foo We propose that the first 3 library reference numbers, i.e 0-2, SHOULD be left for the user (to organize them in a user/group/all fashion) and that the next 3 library numbers, i.e. 3, 4, and 5 resp, SHALL be used for L1, L2, and L3 libraries. It is important, that the library reference numbers that are used follow the same scheme so that unneccessary errors caused by wrong library reference numbers in )COPY commands are avoided. The designer of a )COPYd library MUST propose a library reference number to be used, so that other libraries that are build on top of some library will know where to find it. 2.5 Library initialization -------------------------- The ')COPY 4 foo' command shall load all components of the library and perform the necessary initialization. It SHALL also perform dependency checking as needed, so that the user can use the functions installed by the library without any additional actions. The )COPY command can handle .apl files (i.e. other libraries) recursively. Therefore a library MUST load all libraries that it depends on. 2.6 Double Inclusion -------------------- The library MUST BE stateless, so that loading the same library twice is possible. 2.7 Library Components ---------------------- - 3. Coding Conventions ===================== 3.1 C1 library components are intended be )COPYd at the beginning of the user code. 3.2 The 'base' and 'meta' libraries SHALL )SIC so that subsequent creation of functions is guaranteed to succeed. 3.3 A library must not (permanently) change the default values of system variables and must not create global objects with names other than foo∆... (more to come...) 4. Documentation ================ The library MUST contain sufficient documentation describing how to install and use the library. For simple libraries this can be a few lines (say up to 30) of APL comments at the beginning of the library. For longer texts a separate UTF-8 encoded text file named foo.text shall be used. Formats such as .PDF or Windows .doc SHALL be excluded because they tend to make cut-and-paste from the, hopefully many, examples in the text difficult. (more to come...) 5. File format for C1 Library Components ======================================== After having looked at different existing exchange formats, is looks like UTF8-encoded text files is the way to go to achieve the top-level requirements for C1 library components (i.e. for APL source files). Binary formats are slightly more efficient, but are lack cut-and-paste facilities. 5.1. Encoding ------------- The library shall be a text file containing only valid Unicode characters that are UTF-8 encoded. The first two characters of the text file MUST be #! for C3 components and ⍝! for C2 and C1 components 5.2. Correctness ---------------- The library shall contain correct APL code in the sense that it can be )COPYd into an APL workspace without errors. APL Commands MAY be used, in particular )COPYing of other libraries. L1 library must only use commands defined in the ISO standard. Commands that MAY alter the default variables permanently (such as) LOAD) MUST NOT be used, 5.3 Representation of APL values -------------------------------- Generally speaking any sequence of APL expressions that produces a given APL value can be used in a library. For libraries originated in GNU APL, the )DUMP command or 10 ⎕CR can be used to create such expressions without side-effects. For libraries originated in other APL interpreters other functions may exist that have the desire effect of producing APL code that creates variables with a given value. 5.4 Representation of user-defined APL Functions ------------------------------------------------ There are currently 3 methods to create a user defined function in GNU APL: A. named direct functions, e.g. PLUS ← { ... } , or B. ⎕FX, e.g. ⎕FX 'Z←A PLUS B' 'Z←A + B', or C. The ∇-editor, e.g. ∇Z←A PLUS B Z←A + B ∇ Of these, A. is not portable because direct functions are non-standard. B. is difficult to read if a function gets longer, Therefore method C. MUST be used for user-defined APL functions. 6. Packaging and Storing of Libraries ===================================== 6.1 Location ------------ Libraries are stored on the Web, either as part of the GNU APL project at gnu.org or at some other place. Libraries stored as part of the GNU APL project MUST obey the relevant GNU policies (see e.g. www.gnu.org/prep/maintain/maintain.html, www.gnu.org/server/standards/README.webmastering.html) and MUST follow the guidelines in this document. Libraries stored elsewhere SHOULD follow the guidelines in this document. 6.2 License and Copyright ------------------------- The GNU LGPL license is recommended for all Libraries related to GNU APL. Libraries stored as part of the GNU APL project MUST use a license that is compatible with the GNU GPL or with the GNU LGPL. They MUST provide valid copyright information identifying all non-trivial contributors. Libraries stored elsewhere SHOULD NOT limit the freedom of others to use the code in the library. 6.3 Central Web Page -------------------- The GNU APL project SHOULD provide a web page that contains links to libraries and other code related to GNU APL. (more to come...) 7. References ------------- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.