Search Top Index
HELP ACTIVE_VARIABLES A.Sloman Nov 1986 Active variables allow variables to store multiple values, and allow side effects to be associated with the access or updating of a variable. CONTENTS - (Use <ENTER> g to access required sections) -- Formats for declaring active variables -- Description -- Example - an active identifier of multiplicity 3 -- Accessing the nonactive value -- Making an active identifier local: DLOCAL -- WARNING - use "dlocal" not "vars" -- System active identifiers -- Multiplicity and identprops of active identifiers -- identof(WORD) -> IDENT; -- idval(IDENT) -> ITEM -- nonactive_idval(IDENT) -> ITEM -- valof(WORD) -> ITEM -- nonactive_valof(WORD) -> ITEM -- RELATED DOCUMENTATION -- Formats for declaring active variables ----------------------------- vars active a_var; vars active:N a_var; define active:N a_var ; .... enddefine; define updaterof active:N a_var (v1,v2,..vN); ... enddefine; Where N specifies the 'multiplicity' of the active identifier "a_var" (defaulting to 1 if omitted). Since activeness is an independent attribute of identifiers, it may be specified in conjunction with other identprops, e.g. vars active macro a_var; However, this is ONLY allowable for a multiplicity of 1, i.e. vars active:2 macro a_var; is illegal. -- Description -------------------------------------------------------- Active variables, which strictly speaking should be called active identifiers, are those whose names are used as if they were ordinary identifiers, but which in fact are associated with procedures. The base procedure is run when the identifier is used normally and the updater is run when the identifier occurs on the right of "->". This makes it possible to associate side-effects with the process of accessing or updating the identifier. E.g. the updater can call the error handler if the wrong type of object is assigned. Alternatively the procedures can keep track of the number of accesses. An active identifier has a multiplicity specifying how many results it produces when accessed, and how many items have to be supplied when it is updated. When active identifiers are made local to a procedure with * DLOCAL, the multiplicity is used to determine storage requirements for the saved values. -- Example - an active identifier of multiplicity 3 --------------------- The identifier AV3 will be defined to store three values, and to count the number of accesses in the permanent variable ACC_AV3 and the number of updates in the permanent variable UPD_AV3. The three values will be stored in an inaccessible vector held in a lexical identifier VEC_AC3. vars acc_av3 = 0, upd_av3 = 0; lconstant vec_av3 = {1 2 3}; define active:3 av3; acc_av3 + 1 -> acc_av3; explode(vec_av3) enddefine; define updaterof active:3 av3(x1,x2,x3); lvars x1,x2,x3; fill(x1,x2,x3,vec_av3) ->; upd_av3 + 1 -> upd_av3; enddefine; av3 => ** 1 2 3 4,5,6 -> av3; av3 => ** 4 5 6 av3 + 4 -> av3; av3 => ** 4 5 10 How many times has AV3 been accessed? acc_av3 => ** 4 and updated? upd_av3 => ** 2 In this example the values are stored in a vector. The active variable mechanism does not presuppose this. For example the values might be obtained from a generator function, or read in from a file. Values given to the updater might be output to a device by the updater. In that case the active variable would function as a stream. All that is required is that for an active variable of multiplicity N, the base procedure produces N results and the updater takes N arguments. There need not be any relationship between what they do. Notice that in the above example the use of the "top level" declaration lconstant vec_av3 = {1 2 3}; depends on the fact that Pop-11 supports lexical identifiers that are not local to a procedure but are local to a compilation stream, sometimes referred to as "file_local lexicals". If the variables acc_av3 and upd_av3 were never to be accessed directly by users, but only by procedures, they could have been declared as lvars. -- Accessing the nonactive value -------------------------------------- The syntax word "nonactive", analogous to "nonmac", "nonop" and "nonsyntax" can be used immediately before an active identifier to suppress its invocation, e.g. to discover the real value, as opposed to its active value: nonactive av3=> ** <procedure av3> -- Making an active identifier local: DLOCAL -------------------------- If an active identifier is to be used as local to a procedure it must be declared local using "dlocal". E.g define test; dlocal av3=(99,100,101); av3 enddefine; test() => ** 99 100 101 av3 => ** 4 5 10 -- WARNING - use "dlocal" not "vars" ---------------------------------- "vars" should not be used to declare an identifier as dynamically local. This is because vars av3; would re-declare "av3" as an ordinary non-active identifier, and prevent it working properly as an active identifier thereafter. (Note that you can use "dlocal" to declare all variables, lexical or permanent, as dynamically local: use of "vars" statements inside procedures is thus unnecessary and should be avoided.) -- System active identifiers -------------------------------------------- Examples of active identifiers in the system are: *CURRENT_DIRECTORY, *CURRENT_SECTION *POPDEVERR *POPDEVIN *POPDEVOUT *POPDEVRAW *POP_CALLSTACK_LIM and DLOCAL_PROCESS DLOCAL_CONTEXT, defined in REF * VMCODE/dlocal_context POP_HASH_LIM (defined in HELP * SYSHASH/POP_HASH_LIM) see also $usepop/pop/lib/data/ved_what/popactive for a list of active variables, their function and values. -- Multiplicity and identprops of active identifiers -------------------- An active identifier has a multiplicity N, an integer specifying the number of results returned by its base procedure and required as arguments by its updater: this defaults to 1 if not specified. The procedure "isactive" returns the multiplicity of an active identifier, or false if it not active, e.g. isactive("av3") => ** 3 isactive("acc_av3") => ** <false> Note that the *IDENTPROPS of an active identifier are whatever else it was declared as, and do not reveal its activeness. Procedures that can operate on active identifiers include the following, described in REF * IDENT -- identof(WORD) -> IDENT; Returns the permanent identifier currently attached to WORD. -- idval(IDENT) -> ITEM ITEM -> idval(IDENT) Returns or updates the value cell, running the relevant procedure or its updater if the identifier is active. The updater checks the value of ITEM against the *IDENTTYPE of IDENT -- nonactive_idval(IDENT) -> ITEM ITEM -> nonactive_idval(IDENT) Does not run the procedure associated with an active identifier. -- valof(WORD) -> ITEM ITEM -> valof(WORD) This is functionally equivalent to idval(identof(WORD)) -- nonactive_valof(WORD) -> ITEM ITEM -> nonactive_valof(WORD) This is functionally equivalent to nonactive_idval(identof(WORD)) -- RELATED DOCUMENTATION ---------------------------------------------- HELP *VARIABLES - overview of variables available in POPLOG REF *IDENT, *VMCODE, *WORDS HELP *VARS, *LEXICAL, *DLOCAL, *ISACTIVE --- C.all/help/active_variables ---------------------------------------- --- Copyright University of Sussex 1987. All rights reserved. ----------