Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 4183461[1XA [33X[0;0YSome Tools for Database Handling[133X[101X23[33X[0;0YTwo aims of the tools described in this appendix are[133X45[30X [33X[0;6Yspeeding up selection functions such as [2XAllCharacterTableNames[102X6([14XCTblLib: AllCharacterTableNames[114X) for certain data libraries of [5XGAP[105X7(with not too many entries), in the sense that users can extend the8list of attributes that are treated in a special way[133X910[30X [33X[0;6Yand a programmatic extension for rendering overviews of information11about the contents of databases, using12[2XBrowseTableFromDatabaseIdEnumerator[102X ([14XA.2-2[114X).[133X1314[33X[0;0YThe [5XGAP[105X objects introduced for that are [13Xdatabase id enumerators[113X (see [14XA.1-1[114X)15and [13Xdatabase attributes[113X (see [14XA.1-2[114X).[133X1617[33X[0;0YContrary to the individual interfaces to the [5XGAP[105X manuals (see Section [14X6.6[114X),18the [5XGAP[105X bibliography (see Section [14X6.7[114X), and the overviews of [5XGAP[105X packages,19[5XGAP[105X methods, and Conway polynomials available in [5XGAP[105X (see Section [14X6.11[114X), the20approach that will be described here assumes a special way to access21database entries. Thus it depends on the structure of a given database22whether the tools described here are useful, or whether an individual23interface fits better. Perhaps the example shown in Section [14XA.3[114X gives an24impression what is possible.[133X252627[1XA.1 [33X[0;0Y[5XGAP[105X[101X[1X Objects for Database Handling[133X[101X282930[1XA.1-1 [33X[0;0YDatabase Id Enumerators[133X[101X3132[33X[0;0YA [13Xdatabase id enumerator[113X is a record [3Xr[103X with at least the following33components.[133X3435[8X[10Xidentifiers[110X[8X[108X36[33X[0;6Ya list of [21Xidentifiers[121X of the database entries, which provides a37bijection with these entries,[133X3839[8X[10Xentry[110X[8X[108X40[33X[0;6Ya function that takes [3Xr[103X and an entry in the [10Xidentifiers[110X list, and41returns the corresponding database entry,[133X4243[8X[10Xattributes[110X[8X[108X44[33X[0;6Ythe record whose components are the database attribute records (see45Section [14XA.1-2[114X) for [3Xr[103X; this components is automatically initialized46when [3Xr[103X is created with [2XDatabaseIdEnumerator[102X ([14XA.1-4[114X); database47attributes can be entered with [2XDatabaseAttributeAdd[102X ([14XA.1-5[114X).[133X4849[33X[0;0YIf the [10Xidentifiers[110X list may change over the time (because the database is50extended or corrected) then the following components are supported. They are51used by [2XDatabaseIdEnumeratorUpdate[102X ([14XA.1-7[114X).[133X5253[8X[10Xversion[110X[8X[108X54[33X[0;6Ya [5XGAP[105X object that describes the version of the [10Xidentifiers[110X component,55this can be for example a string describing the time of the last56change (this time need not coincide with the time of the last update);57the default value (useful only for the case that the [10Xidentifiers[110X58component is never changed) is an empty string,[133X5960[8X[10Xupdate[110X[8X[108X61[33X[0;6Ya function that takes [3Xr[103X as its argument, replaces its [10Xidentifiers[110X and62[10Xversion[110X values by up-to-date versions if necessary (for example by63downloading the data), and returns [9Xtrue[109X or [9Xfalse[109X, depending on whether64the update process was successful or not; the default value is65[2XReturnTrue[102X ([14XReference: ReturnTrue[114X),[133X6667[33X[0;0YThe following component is optional.[133X6869[8X[10XisSorted[110X[8X[108X70[33X[0;6Y[9Xtrue[109X means that the [10Xidentifiers[110X list is sorted w.r.t. [5XGAP[105X's ordering71[10X\<[110X; the default is [9Xfalse[109X.[133X7273[33X[0;0YThe idea behind database id enumerator objects is that such an object74defines the set of data covered by database attributes (see Section [14XA.1-2[114X),75it provides the mapping between identifiers and the actual entries of the76database, and it defines when precomputed data of database attributes are77outdated.[133X787980[1XA.1-2 [33X[0;0YDatabase Attributes[133X[101X8182[33X[0;0YA [13Xdatabase attribute[113X is a record [3Xa[103X whose components belong to the aspects of83[13Xdefining[113X the attribute, [13Xaccessing[113X the attribute's data, [13Xcomputing[113X (and84recomputing) data, [13Xstoring[113X data on files, and [13Xchecking[113X data. (Additional85parameters used for creating browse table columns from database attributes86are described in Section [14XA.2-1[114X.)[133X8788[33X[0;0YThe following components are [13Xdefining[113X, except [10Xdescription[110X they are89mandatory.[133X9091[8X[10Xidenumerator[110X[8X[108X92[33X[0;6Ythe database id enumerator to which the attribute [3Xa[103X is related,[133X9394[8X[10Xidentifier[110X[8X[108X95[33X[0;6Ya string that identifies [3Xa[103X among all database attributes for the96underlying database id enumerator (this is used by97[2XBrowseTableFromDatabaseIdEnumerator[102X ([14XA.2-2[114X) and when the data of [3Xa[103X are98entered with [2XDatabaseAttributeSetData[102X ([14XA.1-9[114X), for example when99precomputed values are read from a file),[133X100101[8X[10Xdescription[110X[8X[108X102[33X[0;6Ya string that describes the attribute in human readable form103(currently just for convenience, the default is an empty string).[133X104105[33X[0;0YThe following components are used for [13Xaccessing[113X data. Except [10Xtype[110X, they are106optional, but enough information must be provided in order to make the107database attribute meaningful. If an individual [10XattributeValue[110X function is108available then this function decides what is needed; for the default109function [2XDatabaseAttributeValueDefault[102X ([14XA.1-6[114X), at least one of the110components [10Xname[110X, [10Xdata[110X, [10Xdatafile[110X must be bound (see111[2XDatabaseAttributeValueDefault[102X ([14XA.1-6[114X) for the behaviour in this case).[133X112113[8X[10Xtype[110X[8X[108X114[33X[0;6Yone of the strings [10X"values"[110X or [10X"pairs"[110X; the format of the component115[10Xdata[110X is different for these cases,[133X116117[8X[10Xname[110X[8X[108X118[33X[0;6Yif bound, a string that is the name of a [5XGAP[105X function such that the119database attribute encodes the values of this function for the120database entries; besides the computation of attribute values on121demand (see [2XDatabaseAttributeValueDefault[102X ([14XA.1-6[114X)), this component can122be used by selection functions such as [2XOneCharacterTableName[102X ([14XCTblLib:123OneCharacterTableName[114X) or [2XAllCharacterTableNames[102X ([14XCTblLib:124AllCharacterTableNames[114X), which take [5XGAP[105X functions and prescribed125return values as their arguments –of course these functions must then126be prepared to deal with database attributes.[133X127128[8X[10Xdata[110X[8X[108X129[33X[0;6Yif bound, the data for this attribute; if the component [10Xtype[110X has the130value [10X"values"[110X then the value is a list, where the entry at position131[3Xi[103X, if bound, belongs to the [3Xi[103X-th entry of the [10Xidentifiers[110X list of132[10Xidenumerator[110X; if [10Xtype[110X is [10X"pairs"[110X then the value is a record with the133components [10Xautomatic[110X and [10Xnonautomatic[110X, and the values of these134components are lists such that each entry is a list of length two135whose first entry occurs in the [10Xidentifiers[110X list of [3Xa[103X[10X.idenumerator[110X and136whose second entry encodes the corresponding attribute value,[133X137138[8X[10Xdatafile[110X[8X[108X139[33X[0;6Yif bound, the absolute name of a file that contains the data for this140attribute,[133X141142[8X[10XattributeValue[110X[8X[108X143[33X[0;6Ya function that takes [3Xa[103X and an [10Xidentifiers[110X entry of its [10Xidenumerator[110X144value, and returns the attribute value for this identifier; typically145this is [13Xnot[113X a table cell data object that can be shown in a browse146table, cf. the [10XviewValue[110X component; the default is147[2XDatabaseAttributeValueDefault[102X ([14XA.1-6[114X) (Note that using individual148[10XattributeValue[110X functions, one can deal with database attributes149independent of actually stored data, for example without precomputed150values, such that the values are computed on demand and afterwards are151cached.),[133X152153[8X[10XdataDefault[110X[8X[108X154[33X[0;6Ya [5XGAP[105X object that is regarded as the attribute value for those155database entries for which [10Xdata[110X, [10Xdatafile[110X, and [10Xname[110X do not provide156values; the default value is an empty string [10X""[110X,[133X157158[8X[10Xeval[110X[8X[108X159[33X[0;6Yif this component is bound, the value is assumed to be a function that160takes [3Xa[103X and a value from its [10Xdata[110X component, and returns the actual161attribute value; this can be useful if one does not want to create all162attribute values in advance, because this would be space or time163consuming; another possible aspect of the [10Xeval[110X component is that it164may be used to strip off comments that are perhaps contained in [10Xdata[110X165entries,[133X166167[8X[10XisSorted[110X[8X[108X168[33X[0;6Yif this component is bound to [9Xtrue[109X and if [10Xtype[110X is [10X"pairs"[110X then it is169assumed that the two lists in the [10Xdata[110X record of [3Xa[103X are sorted w.r.t.170[5XGAP[105X's ordering [10X\<[110X; the default is [9Xfalse[109X,[133X171172[33X[0;0YThe following optional components are needed for [13Xcomputing[113X (or recomputing)173data with [2XDatabaseAttributeCompute[102X ([14XA.1-8[114X). This is useful mainly for174databases which can change over the time.[133X175176[8X[10Xversion[110X[8X[108X177[33X[0;6Ythe [5XGAP[105X object that is the [10Xversion[110X component of the [10Xidenumerator[110X178component at the time when the stored data were entered; this value is179used by [2XDatabaseIdEnumeratorUpdate[102X ([14XA.1-7[114X) for deciding whether the180attribute values are outdated; if [3Xa[103X[10X.datafile[110X is bound then it is181assumed that the [10Xversion[110X component is set when this file is read, for182example in the function [2XDatabaseAttributeSetData[102X ([14XA.1-9[114X),[133X183184[8X[10Xupdate[110X[8X[108X185[33X[0;6Ya function that takes [3Xa[103X as its argument, adjusts its data components186to the current values of [3Xa[103X[10X.dbidenum[110X if necessary, sets the [10Xversion[110X187component to that of [3Xa[103X[10X.dbidenum[110X, and returns [9Xtrue[109X or [9Xfalse[109X, depending188on whether the update process was successful or not; the default value189is [2XReturnTrue[102X ([14XReference: ReturnTrue[114X),[133X190191[8X[10XneededAttributes[110X[8X[108X192[33X[0;6Ya list of attribute [10Xidentifier[110X strings such that the values of these193attributes are needed in the computations for the current one, and194therefore these should be updated/recomputed in advance; it is assumed195that the [10XneededAttributes[110X components of all database attributes of196[3Xa[103X[10X.idenumerator[110X define a partial ordering; the default is an empty197list,[133X198199[8X[10XprepareAttributeComputation[110X[8X[108X200[33X[0;6Ya function with argument [3Xa[103X that must be called before the computations201for the current attribute are started; the default value is [2XReturnTrue[102X202([14XReference: ReturnTrue[114X),[133X203204[8X[10XcleanupAfterAttibuteComputation[110X[8X[108X205[33X[0;6Ya function with argument [3Xa[103X that must be called after the computations206for the current attribute are finished; the default value is207[2XReturnTrue[102X ([14XReference: ReturnTrue[114X), and[133X208209[8X[10Xcreate[110X[8X[108X210[33X[0;6Ya function that takes a database attribute and an entry in the211[10Xidentifiers[110X list of its database id enumerator, and returns either the212entry that shall be stored in the [10Xdata[110X component, as the value for the213given identifier (if this value shall be stored in the [10Xdata[110X component214of [3Xa[103X) or the [10XdataDefault[110X component of [3Xa[103X (if this value shall [13Xnot[113X be215stored); in order to get the actual attribute value, the [10Xeval[110X function216of [3Xa[103X, if bound, must be called with the return value. This function217may assume that the [10XprepareAttributeComputation[110X function has been218called in advance, and that the [10XcleanupAfterAttibuteComputation[110X219function will be called later. The [10Xcreate[110X function is [13Xnot[113X intended to220compute an individual attribute value on demand, use a [10Xname[110X component221for that. (A stored [10Xname[110X function is used to provide a default for the222[10Xcreate[110X function; without [10Xname[110X component, there is no default for223[10Xcreate[110X.)[133X224225[33X[0;0YThe following optional component is needed for [13Xstoring[113X data on files.[133X226227[8X[10Xstring[110X[8X[108X228[33X[0;6Yif bound, a function that takes the pair consisting of an identifier229and the return value of the [10Xcreate[110X function for this identifier, and230returns a string that shall represent this value when the data are231printed to a file; the default function returns the [2XString[102X ([14XReference:232String[114X) value of the second argument.[133X233234[33X[0;0YThe following optional component is needed for [13Xchecking[113X stored data.[133X235236[8X[10Xcheck[110X[8X[108X237[33X[0;6Ya function that takes a string that occurs in the [10Xidentifiers[110X list of238the [10Xidenumerator[110X record, and returns [9Xtrue[109X if the attribute value239stored for this string is reasonable, and something different from240[9Xtrue[109X if an error was detected. (One could argue that these tests can241be performed also when the values are computed, but consistency checks242may involve several entries; besides that, checking may be cheaper243than recomputing.)[133X244245246[1XA.1-3 [33X[0;0YHow to Deal with Database Id Enumerators and Database Attributes[133X[101X247248[33X[0;0YThe idea is to start with a database id enumerator (see [14XA.1-1[114X), constructed249with [2XDatabaseIdEnumerator[102X ([14XA.1-4[114X), and to define database attributes for it250(see [14XA.1-2[114X), using [2XDatabaseAttributeAdd[102X ([14XA.1-5[114X). The attribute values can be251precomputed and stored on files, or they are computed when the attribute252gets defined, or they are computed on demand.[133X253254[33X[0;0YThe function [2XDatabaseAttributeCompute[102X ([14XA.1-8[114X) can be used to [21Xrefresh[121X the255attribute values, that is, all values or selected values can be recomputed;256this can be necessary for example when the underlying database id enumerator257gets extended.[133X258259[33X[0;0YIn data files, the function [2XDatabaseAttributeSetData[102X ([14XA.1-9[114X) can be used to260fill the [10Xdata[110X component of the attribute.[133X261262[1XA.1-4 DatabaseIdEnumerator[101X263264[29X[2XDatabaseIdEnumerator[102X( [3Xarec[103X ) [32X function265[6XReturns:[106X [33X[0;10Ya shallow copy of the record [3Xarec[103X, extended by default values.[133X266267[33X[0;0YFor a record [3Xarec[103X, [2XDatabaseIdEnumerator[102X checks whether the mandatory268components of a database id enumerator (see Section [14XA.1-1[114X) are present,269initializes the [10Xattributes[110X component, sets the defaults for unbound optional270components (see [14XA.2-1[114X), and returns the resulting record.[133X271272[33X[0;0YA special database attribute (see Section [14XA.1-2[114X) with [10Xidentifier[110X value273[10X"self"[110X is constructed automatically for the returned record by274[2XDatabaseIdEnumerator[102X; its [10XattributeValue[110X function simply returns its second275argument (the identifier). The optional components of this attribute are276derived from components of the database id enumerator, so these components277(see [14XA.2-1[114X) are supported for [3Xarec[103X. A typical use of the [10X"self"[110X attribute is278to provide the first column in browse tables constructed by279[2XBrowseTableFromDatabaseIdEnumerator[102X ([14XA.2-2[114X).[133X280281[1XA.1-5 DatabaseAttributeAdd[101X282283[29X[2XDatabaseAttributeAdd[102X( [3Xdbidenum[103X, [3Xarec[103X ) [32X function284285[33X[0;0YFor a database id enumerator [3Xdbidenum[103X and a record [3Xarec[103X,286[2XDatabaseAttributeAdd[102X checks whether the mandatory components of a database287attribute, except [10Xidenumerator[110X, are present in [3Xarec[103X (see Section [14XA.1-2[114X),288sets the [10Xidenumerator[110X component, and sets the defaults for unbound optional289components (see [14XA.2-1[114X).[133X290291[1XA.1-6 DatabaseAttributeValueDefault[101X292293[29X[2XDatabaseAttributeValueDefault[102X( [3Xattr[103X, [3Xid[103X ) [32X function294[6XReturns:[106X [33X[0;10Ythe value of the database attribute [3Xattr[103X at [3Xid[103X.[133X295296[33X[0;0YFor a database attribute [3Xattr[103X and an entry [3Xid[103X of the [10Xidentifiers[110X list of the297underlying database id enumerator, [2XDatabaseAttributeValueDefault[102X takes the298[10Xdata[110X entry for [3Xid[103X, applies the [10Xeval[110X function of [3Xattr[103X to it if available and299returns the result.[133X300301[33X[0;0YSo the question is how to get the [10Xdata[110X entry.[133X302303[33X[0;0YFirst, if the [10Xdata[110X component of [3Xattr[103X is not bound then the file given by the304[10Xdatafile[110X component of [3Xattr[103X, if available, is read, and otherwise305[2XDatabaseAttributeCompute[102X ([14XA.1-8[114X) is called; afterwards it is assumed that306the [10Xdata[110X component is bound.[133X307308[33X[0;0YThe further steps depend on the [10Xtype[110X value of [3Xattr[103X.[133X309310[33X[0;0YIf the [10Xtype[110X value of [3Xattr[103X is [10X"pairs"[110X then the [10Xdata[110X entry for [3Xid[103X is either311contained in the [10Xautomatic[110X or in the [10Xnonautomatic[110X list of [3Xattr[103X[10X.data[110X, or it312is given by the [10XdataDefault[110X value of [3Xattr[103X. (So a perhaps available [10Xname[110X313function is [13Xnot[113X used to compute the value for a missing [10Xdata[110X entry.)[133X314315[33X[0;0YIf the [10Xtype[110X value of [3Xattr[103X is [10X"values"[110X then the [10Xdata[110X entry for [3Xid[103X is computed316as follows. Let [22Xn[122X be the position of [3Xid[103X in the [10Xidentifiers[110X component of the317database id enumerator. If the [22Xn[122X-th entry of the [10Xdata[110X component of [3Xattr[103X is318bound then take it; otherwise if the [10Xname[110X component is bound then apply it319to [3Xid[103X and take the return value; otherwise take the [10XdataDefault[110X value.[133X320321[33X[0;0YIf one wants to introduce a database attribute where this functionality is322not suitable then another –more specific– function must be entered as the323component [10XattributeValue[110X of such an attribute.[133X324325[1XA.1-7 DatabaseIdEnumeratorUpdate[101X326327[29X[2XDatabaseIdEnumeratorUpdate[102X( [3Xdbidenum[103X ) [32X function328[6XReturns:[106X [33X[0;10Y[9Xtrue[109X or [9Xfalse[109X.[133X329330[33X[0;0YFor a database id enumerator [3Xdbidenum[103X (see Section [14XA.1-1[114X),331[2XDatabaseIdEnumeratorUpdate[102X first calls the [10Xupdate[110X function of [3Xdbidenum[103X.332Afterwards, the [10Xupdate[110X components of those of its [10Xattributes[110X records are333called for which the [10Xversion[110X component differs from that of [3Xdbidenum[103X.[133X334335[33X[0;0YThe order in which the database attributes are updates is determined by the336[10XneededAttributes[110X component.[133X337338[33X[0;0YThe return value is [9Xtrue[109X if all these functions return [9Xtrue[109X, and [9Xfalse[109X339otherwise.[133X340341[33X[0;0YWhen [2XDatabaseIdEnumeratorUpdate[102X has returned [9Xtrue[109X, the data described by342[3Xdbidenum[103X and its database attributes are consistent and up to date.[133X343344[1XA.1-8 DatabaseAttributeCompute[101X345346[29X[2XDatabaseAttributeCompute[102X( [3Xdbidenum[103X, [3Xattridentifier[103X[, [3Xwhat[103X] ) [32X function347[6XReturns:[106X [33X[0;10Y[9Xtrue[109X or [9Xfalse[109X.[133X348349[33X[0;0YThis function returns [9Xfalse[109X if [3Xdbidenum[103X is not a database id enumerator, or350if it does not have a database attribute with [10Xidentifier[110X value351[3Xattridentifier[103X, or if this attribute does not have a [10Xcreate[110X function.[133X352353[33X[0;0YOtherwise the [10XprepareAttributeComputation[110X function is called, the [10Xdata[110X354entries for the database attribute are (re)computed, the355[10XcleanupAfterAttibuteComputation[110X function is called, and [9Xtrue[109X is returned.[133X356357[33X[0;0YThe optional argument [3Xwhat[103X determines which values are computed. Admissible358values are[133X359360[8X[10X"all"[110X[8X[108X361[33X[0;6Yall [10Xidentifiers[110X entries of [3Xdbidenum[103X,[133X362363[8X[10X"automatic"[110X[8X (the default)[108X364[33X[0;6Ythe same as [10X"all"[110X if the [10Xtype[110X value of the database attribute is365[10X"values"[110X, otherwise only the values for the [10X"automatic"[110X component are366computed,[133X367368[8X[10X"new"[110X[8X[108X369[33X[0;6Ystored values are not recomputed.[133X370371[1XA.1-9 DatabaseAttributeSetData[101X372373[29X[2XDatabaseAttributeSetData[102X( [3Xdbidenum[103X, [3Xattridentifier[103X, [3Xversion[103X, [3Xdata[103X ) [32X function374375[33X[0;0YLet [3Xdbidenum[103X be a database id enumerator (see Section [14XA.1-1[114X), [3Xattridentifier[103X376be a string that is the [10Xidentifier[110X value of a database attribute of377[3Xdbidenum[103X, [3Xdata[103X be the [10Xdata[110X list or record for the database attribute378(depending on its [10Xtype[110X value), and [3Xversion[103X be the corresponding [10Xversion[110X379value.[133X380381[33X[0;0Y[2XDatabaseAttributeSetData[102X sets the [10Xdata[110X and [10Xversion[110X components of the382attribute. This function can be used for example in data files.[133X383384385[1XA.2 [33X[0;0YUsing Database Attributes for Browse Tables[133X[101X386387388[1XA.2-1 [33X[0;0YBrowse Relevant Components of Database Attributes[133X[101X389390[33X[0;0YThe following optional components of database id enumerators and database391attributes are used by [2XBrowseTableFromDatabaseIdEnumerator[102X ([14XA.2-2[114X).[133X392393[8X[10XviewLabel[110X[8X[108X394[33X[0;6Yif bound, a table cell data object (see395[2XBrowseData.IsBrowseTableCellData[102X ([14X4.2-1[114X)) that gives a [13Xshort[113X396description of the attribute, which is used as the column label in397browse tables created with [2XBrowseTableFromDatabaseIdEnumerator[102X398([14XA.2-2[114X); the default for database attributes is the [10Xname[110X component, if399bound, and otherwise the [10Xidentifier[110X component; the default for400database id enumerators is the string [10X"name"[110X,[133X401402[8X[10XviewValue[110X[8X[108X403[33X[0;6Yif bound, a function that takes the output of the [10XattributeValue[110X404function and returns a table cell data object (see405[2XBrowseData.IsBrowseTableCellData[102X ([14X4.2-1[114X)) that is used as the entry of406the corresponding column in browse tables created with407[2XBrowseTableFromDatabaseIdEnumerator[102X ([14XA.2-2[114X); the default is [2XString[102X408([14XReference: String[114X),[133X409410[8X[10XviewSort[110X[8X[108X411[33X[0;6Yif bound, a comparison function that takes two database attribute412values and returns [9Xtrue[109X if the first value is regarded as smaller than413the second when the column corresponding to the attribute in the414browse table constructed by [2XBrowseTableFromDatabaseIdEnumerator[102X415([14XA.2-2[114X) gets sorted, and [9Xfalse[109X otherwise; the default is [5XGAP[105X's [10X\<[110X416operation,[133X417418[8X[10XsortParameters[110X[8X[108X419[33X[0;6Yif bound, a list in the same format as the last argument of420[10XBrowseData.SetSortParameters[110X, which is used for the column421corresponding to the attribute in the browse table constructed by422[2XBrowseTableFromDatabaseIdEnumerator[102X ([14XA.2-2[114X); the default is an empty423list,[133X424425[8X[10XwidthCol[110X[8X[108X426[33X[0;6Yif bound, the width of the column in the browse table constructed by427[2XBrowseTableFromDatabaseIdEnumerator[102X ([14XA.2-2[114X); if a column width is428prescribed this way then the function stored in the [10XattributeValue[110X429component must return either a list of attribute lines that fit into430the column or a plain string (which then gets formatted as required);431there is no default for this component, meaning that the column width432is computed as the maximum of the widths of the column label and of433all entries in the column if no value is bound,[133X434435[8X[10Xalign[110X[8X[108X436[33X[0;6Yif bound, the alignment of the values in the column of the browse437table constructed by [2XBrowseTableFromDatabaseIdEnumerator[102X ([14XA.2-2[114X);438admissible values are substrings of [10X"bclt"[110X, see439[2XBrowseData.IsBrowseTableCellData[102X ([14X4.2-1[114X); the default is right and440vertically centered, but note that if the [10XviewValues[110X function returns441a record (see [2XBrowseData.IsBrowseTableCellData[102X ([14X4.2-1[114X)) then the442alignment prescribed by this record is preferred,[133X443444[8X[10XcategoryValue[110X[8X[108X445[33X[0;6Yif bound, a function that is similar to the [10XviewValue[110X component but446may return a different value; for example if the column in the browse447table belongs to a property and the [10XviewValue[110X function returns448something like [10X"+"[110X or [10X"-"[110X, it may be useful that the category rows449show a textual description of the property values; the default value450is the [10XviewValue[110X component; if the value is a record then its [10Xrows[110X451component is taken for forming category rows, if the value is an452attribute line (see [2XNCurses.IsAttributeLine[102X ([14X2.2-3[114X)) then there is453exactly this category row, and otherwise the value is regarded as a454list of attribute lines, which is either concatenated to one category455row or turned into individual category rows, depending on the456[10XsortParameters[110X value.[133X457458[1XA.2-2 BrowseTableFromDatabaseIdEnumerator[101X459460[29X[2XBrowseTableFromDatabaseIdEnumerator[102X( [3Xdbidenum[103X, [3Xlabelids[103X, [3Xcolumnids[103X[, [3Xheader[103X[, [3Xfooter[103X[, [3Xchoice[103X]]] ) [32X function461[6XReturns:[106X [33X[0;10Ya record that can be used as the input of [2XNCurses.BrowseGeneric[102X462([14X4.3-1[114X).[133X463464[33X[0;0YFor a database id enumerator [3Xdbidenum[103X (see Section [14XA.1-1[114X) and two lists465[3Xlabelids[103X and [3Xcolumnids[103X of [10Xidentifier[110X values of database attributes stored in466[3Xdbidenum[103X, [2XBrowseTableFromDatabaseIdEnumerator[102X returns a browse table467(see [2XBrowseData.IsBrowseTable[102X ([14X4.2-3[114X)) whose columns are given by the values468of the specified database attributes. The columns listed in [3Xlabelids[103X are469used to provide row label columns of the browse table, the columns listed in470[3Xcolumnids[103X yield main table columns. [3Xcolumnids[103X must be nonempty.[133X471472[33X[0;0YIf the optional arguments [3Xheader[103X and [3Xfooter[103X are given then they must be473lists or functions or records that are admissible for the [10Xheader[110X and [10Xfooter[110X474components of the [10Xwork[110X record of the browse table, see475[2XBrowseData.IsBrowseTable[102X ([14X4.2-3[114X).[133X476477[33X[0;0YThe optional argument [3Xchoice[103X, if given, must be a subset of478[3Xdbidenum[103X[10X.identifiers[110X. The rows of the returned browse table are then479restricted to this subset.[133X480481[33X[0;0YThe returned browse table does not support [21XClick[121X events or return values.[133X482483484[1XA.3 [33X[0;0YExample: Database Id Enumerators and Database Attributes[133X[101X485486[33X[0;0YAs an example for the functions introduced in this appendix, we introduce487the [13Xdatabase of small integers[113X. For that, we fix a positive integer [22Xn[122X and488consider the integers from [22X1[122X to [22Xn[122X as the entries of our database. Using489these integers as their own identifiers, we construct the database id490enumerator.[133X491492[4X[32X Example [32X[104X493[4X[25Xgap>[125X [27Xn:= 100;;[127X[104X494[4X[25Xgap>[125X [27Xsmallintenum1:= DatabaseIdEnumerator( rec([127X[104X495[4X[25X>[125X [27X identifiers:= [ 1 .. n ],[127X[104X496[4X[25X>[125X [27X entry:= function( dbidenum, id ) return id; end,[127X[104X497[4X[25X>[125X [27X ) );;[127X[104X498[4X[32X[104X499500[33X[0;0YExamples of attributes for this database are the properties whether or not501an integer is a prime or a prime power. There are global [5XGAP[105X functions502[2XIsPrimeInt[102X ([14XReference: IsPrimeInt[114X) and [2XIsPrimePowerInt[102X ([14XReference:503IsPrimePowerInt[114X) for computing these properties, so we can define these504database attributes via a [10Xname[110X component; we choose [10X"values"[110X as the [10Xtype[110X505value, so the values ([9Xtrue[109X or [9Xfalse[109X) are stored in a list of length [22Xn[122X for506each of the two database attributes.[133X507508[4X[32X Example [32X[104X509[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum1, rec([127X[104X510[4X[25X>[125X [27X identifier:= "primes",[127X[104X511[4X[25X>[125X [27X type:= "values",[127X[104X512[4X[25X>[125X [27X name:= "IsPrimeInt",[127X[104X513[4X[25X>[125X [27X ) );[127X[104X514[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum1, rec([127X[104X515[4X[25X>[125X [27X identifier:= "prime powers",[127X[104X516[4X[25X>[125X [27X type:= "values",[127X[104X517[4X[25X>[125X [27X name:= "IsPrimePowerInt",[127X[104X518[4X[25X>[125X [27X ) );[127X[104X519[4X[32X[104X520521[33X[0;0YSimilarly, we consider the prime factors as a database attribute.[133X522523[4X[32X Example [32X[104X524[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum1, rec([127X[104X525[4X[25X>[125X [27X identifier:= "factors",[127X[104X526[4X[25X>[125X [27X type:= "values",[127X[104X527[4X[25X>[125X [27X name:= "Factors",[127X[104X528[4X[25X>[125X [27X ) );[127X[104X529[4X[32X[104X530531[33X[0;0YAnother example of an attribute of integers is the residue modulo [22X11[122X. We do532not want to introduce a global [5XGAP[105X function for computing the value, so we533use the [10Xcreate[110X component in order to define the attribute; again, the values534(integers from [22X0[122X to [22X10[122X) are stored in a list of length [22Xn[122X.[133X535536[4X[32X Example [32X[104X537[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum1, rec([127X[104X538[4X[25X>[125X [27X identifier:= "residue mod 11",[127X[104X539[4X[25X>[125X [27X type:= "values",[127X[104X540[4X[25X>[125X [27X create:= function( attr, id ) return id mod 11; end,[127X[104X541[4X[25X>[125X [27X ) );[127X[104X542[4X[32X[104X543544[33X[0;0YSome integers are values of [2XFactorial[102X ([14XReference: Factorial[114X), and we want to545record this information and show it in a browse table. For most integers,546nothing is stored and shown for this attribute, so we choose the [10Xtype[110X value547[10X"pairs"[110X and precompute the information for the [10Xdata[110X component. (The default548for the [10XdataDefault[110X component is an empty string, which is fine; so we need549not prescribe this component.)[133X550551[4X[32X Example [32X[104X552[4X[25Xgap>[125X [27Xfactorialdata:= function( n )[127X[104X553[4X[25X>[125X [27X local result, i, f;[127X[104X554[4X[25X>[125X [27X result:= []; i:= 1; f:= 1;;[127X[104X555[4X[25X>[125X [27X while f <= n do[127X[104X556[4X[25X>[125X [27X Add( result, [ f, i ] ); i:= i + 1; f:= f * i;[127X[104X557[4X[25X>[125X [27X od;[127X[104X558[4X[25X>[125X [27X return result;[127X[104X559[4X[25X>[125X [27X end;;[127X[104X560[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum1, rec([127X[104X561[4X[25X>[125X [27X identifier:= "inverse factorial",[127X[104X562[4X[25X>[125X [27X type:= "pairs",[127X[104X563[4X[25X>[125X [27X data:= rec( automatic:= factorialdata( n ), nonautomatic:= [] ),[127X[104X564[4X[25X>[125X [27X isSorted:= true,[127X[104X565[4X[25X>[125X [27X ) );[127X[104X566[4X[32X[104X567568[33X[0;0YWe use this setup for creating a browse table. The integers are shown as the569first column, using the [10X"self"[110X attribute. This attribute can be used as a570column of row labels (useful if we want to keep the column visible when one571scrolls the table to the right) or as a column in the main table (useful if572we want to search for the values); here we choose the former possibility.[133X573574[4X[32X Example [32X[104X575[4X[25Xgap>[125X [27Xt1:= BrowseTableFromDatabaseIdEnumerator( smallintenum1,[127X[104X576[4X[25X>[125X [27X [ "self" ],[127X[104X577[4X[25X>[125X [27X [ "primes", "prime powers", "factors", "residue mod 11",[127X[104X578[4X[25X>[125X [27X "inverse factorial" ] );;[127X[104X579[4X[32X[104X580581[33X[0;0YThe following session shows some of the features of the browse table.[133X582583[4X[32X Example [32X[104X584[4X[25Xgap>[125X [27Xnop:= [ 14, 14, 14, 14, 14, 14 ];; # ``do nothing''[127X[104X585[4X[25Xgap>[125X [27Xsample_session:= Concatenation([127X[104X586[4X[25X>[125X [27X # categorize by the first column, expand categories, wait, reset[127X[104X587[4X[25X>[125X [27X nop, "scsc", nop, "X", nop, "!",[127X[104X588[4X[25X>[125X [27X # sort the residue column, wait, reset[127X[104X589[4X[25X>[125X [27X "scrrrso", nop, "!",[127X[104X590[4X[25X>[125X [27X # categorize by the inverse factorial column[127X[104X591[4X[25X>[125X [27X "rscsrdx", nop, "!",[127X[104X592[4X[25X>[125X [27X # and quit the application[127X[104X593[4X[25X>[125X [27X "qQ" );;[127X[104X594[4X[25Xgap>[125X [27XBrowseData.SetReplay( sample_session );[127X[104X595[4X[25Xgap>[125X [27XNCurses.BrowseGeneric( t1 );[127X[104X596[4X[25Xgap>[125X [27XBrowseData.SetReplay( false );[127X[104X597[4X[25Xgap>[125X [27XUnbind( t1.dynamic.replay );[127X[104X598[4X[32X[104X599600[33X[0;0Y(Note that the last statement above is necessary to run the session more601than once.) The result is not too bad but we can improve the table, using602the optional components of database attributes, as follows.[133X603604[30X [33X[0;6YThe strings [10X"true"[110X and [10X"false"[110X shown for the Boolean valued database605attributes can be replaced by the perhaps more suggestive strings [10X"+"[110X606and [10X"-"[110X (or perhaps an empty string instead of [10X"-"[110X).[133X607608[30X [33X[0;6YThe alignment of values inside their columns can be customized.[133X609610[30X [33X[0;6YWhen the browse table is categorized by a column then the values in611this column do usually not provide suitable category rows; we can612prescribe individual category values.[133X613614[30X [33X[0;6YThe column labels can be customized.[133X615616[30X [33X[0;6YWhere the lexicographic order is not appropriate for sorting table617entries, we can prescribe an individual comparison function.[133X618619[30X [33X[0;6YSort parameters can be customized.[133X620621[30X [33X[0;6YWe can prescribe the width of a column, and thus distribute the622attribute values for this column to several rows when the values are623too long.[133X624625[30X [33X[0;6YFinally, in the call of [2XBrowseTableFromDatabaseIdEnumerator[102X ([14XA.2-2[114X),626we can add a header to the browse table.[133X627628[33X[0;0YWe create a new database id enumerator and the corresponding browse table,629in order to be able to compare the behaviour of the two objects. However, we630assume that the variables [10Xn[110X and [10Xfactorialdata[110X are already available.[133X631632[4X[32X Example [32X[104X633[4X[25Xgap>[125X [27Xsmallintenum2:= DatabaseIdEnumerator( rec([127X[104X634[4X[25X>[125X [27X identifiers:= [ 1 .. n ],[127X[104X635[4X[25X>[125X [27X entry:= function( dbidenum, id ) return id; end,[127X[104X636[4X[25X>[125X [27X viewLabel:= "",[127X[104X637[4X[25X>[125X [27X ) );;[127X[104X638[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum2, rec([127X[104X639[4X[25X>[125X [27X identifier:= "primes",[127X[104X640[4X[25X>[125X [27X type:= "values",[127X[104X641[4X[25X>[125X [27X name:= "IsPrimeInt",[127X[104X642[4X[25X>[125X [27X viewLabel:= "prime?",[127X[104X643[4X[25X>[125X [27X viewValue:= value -> BrowseData.ReplacedEntry( value,[127X[104X644[4X[25X>[125X [27X [ true, false ], [ "+", "-" ] ),[127X[104X645[4X[25X>[125X [27X sortParameters:= [ "add counter on categorizing", "yes" ],[127X[104X646[4X[25X>[125X [27X align:= "c",[127X[104X647[4X[25X>[125X [27X categoryValue:= value -> BrowseData.ReplacedEntry( value,[127X[104X648[4X[25X>[125X [27X [ true, false ], [ "prime", "nonprime" ] ),[127X[104X649[4X[25X>[125X [27X ) );[127X[104X650[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum2, rec([127X[104X651[4X[25X>[125X [27X identifier:= "prime powers",[127X[104X652[4X[25X>[125X [27X type:= "values",[127X[104X653[4X[25X>[125X [27X name:= "IsPrimePowerInt",[127X[104X654[4X[25X>[125X [27X viewLabel:= "prime power?",[127X[104X655[4X[25X>[125X [27X viewValue:= value -> BrowseData.ReplacedEntry( value,[127X[104X656[4X[25X>[125X [27X [ true, false ], [ "+", "-" ] ),[127X[104X657[4X[25X>[125X [27X sortParameters:= [ "add counter on categorizing", "yes" ],[127X[104X658[4X[25X>[125X [27X align:= "c",[127X[104X659[4X[25X>[125X [27X categoryValue:= value -> BrowseData.ReplacedEntry( value,[127X[104X660[4X[25X>[125X [27X [ true, false ], [ "prime power", "not prime power" ] ),[127X[104X661[4X[25X>[125X [27X ) );[127X[104X662[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum2, rec([127X[104X663[4X[25X>[125X [27X identifier:= "factors",[127X[104X664[4X[25X>[125X [27X type:= "values",[127X[104X665[4X[25X>[125X [27X name:= "Factors",[127X[104X666[4X[25X>[125X [27X viewLabel:= "factors",[127X[104X667[4X[25X>[125X [27X viewValue:= value -> JoinStringsWithSeparator( List( value, String ),[127X[104X668[4X[25X>[125X [27X " * "),[127X[104X669[4X[25X>[125X [27X widthCol:= 10,[127X[104X670[4X[25X>[125X [27X ) );[127X[104X671[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum2, rec([127X[104X672[4X[25X>[125X [27X identifier:= "residue mod 11",[127X[104X673[4X[25X>[125X [27X type:= "values",[127X[104X674[4X[25X>[125X [27X create:= function( attr, id ) return id mod 11; end,[127X[104X675[4X[25X>[125X [27X viewSort:= BrowseData.SortAsIntegers,[127X[104X676[4X[25X>[125X [27X categoryValue:= res -> Concatenation( String( res ), " mod 11" ),[127X[104X677[4X[25X>[125X [27X ) );[127X[104X678[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum2, rec([127X[104X679[4X[25X>[125X [27X identifier:= "inverse factorial",[127X[104X680[4X[25X>[125X [27X type:= "pairs",[127X[104X681[4X[25X>[125X [27X data:= rec( automatic:= factorialdata( n ), nonautomatic:= [] ),[127X[104X682[4X[25X>[125X [27X isSorted:= true,[127X[104X683[4X[25X>[125X [27X categoryValue:= function( k )[127X[104X684[4X[25X>[125X [27X if k = "" then[127X[104X685[4X[25X>[125X [27X return "(no factorial)";[127X[104X686[4X[25X>[125X [27X else[127X[104X687[4X[25X>[125X [27X return Concatenation( String( k ), "!" );[127X[104X688[4X[25X>[125X [27X fi;[127X[104X689[4X[25X>[125X [27X end,[127X[104X690[4X[25X>[125X [27X ) );[127X[104X691[4X[25Xgap>[125X [27Xt2:= BrowseTableFromDatabaseIdEnumerator( smallintenum2,[127X[104X692[4X[25X>[125X [27X [ "self" ],[127X[104X693[4X[25X>[125X [27X [ "primes", "prime powers", "factors", "residue mod 11",[127X[104X694[4X[25X>[125X [27X "inverse factorial" ],[127X[104X695[4X[25X>[125X [27X t -> BrowseData.HeaderWithRowCounter( t, "Small integers", n ) );;[127X[104X696[4X[32X[104X697698[33X[0;0YWe run the same session as with the browse table for [10Xsmallintenum1[110X.[133X699700[4X[32X Example [32X[104X701[4X[25Xgap>[125X [27XBrowseData.SetReplay( sample_session );[127X[104X702[4X[25Xgap>[125X [27XNCurses.BrowseGeneric( t2 );[127X[104X703[4X[25Xgap>[125X [27XBrowseData.SetReplay( false );[127X[104X704[4X[25Xgap>[125X [27XUnbind( t2.dynamic.replay );[127X[104X705[4X[32X[104X706707[33X[0;0YAnother possibility to change the look of the table is to combine the708columns for the two Boolean valued database attributes in one column, by709showing the string [10X"+"[110X for prime powers, as before, and showing this string710in boldface red if the number in question is a prime. We implement this idea711in the following database attribute. However, note that this can be a bad712idea because text attributes may be not supported in the user's terminal713(see Section [14X2.1-7[114X), or the user may have difficulties to see or to714distinguish colors; also, it must be documented which information is encoded715in the table, and the column label might be not sufficient for explaining716what the text attributes mean. Alternatively, we could show for example717combined symbols such as [10X++[110X, [10X+-[110X, [10X--[110X for primes, prime powers, and718non-prime-powers, respectively. (We see that besides these issues, the719required [5XGAP[105X code is more involved than what is needed for the examples720above.)[133X721722[4X[32X Example [32X[104X723[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum2, rec([127X[104X724[4X[25X>[125X [27X identifier:= "primes & prime powers",[127X[104X725[4X[25X>[125X [27X type:= "values",[127X[104X726[4X[25X>[125X [27X create:= function( attr, id )[127X[104X727[4X[25X>[125X [27X if IsPrimeInt( id ) then[127X[104X728[4X[25X>[125X [27X return 2;[127X[104X729[4X[25X>[125X [27X elif IsPrimePowerInt( id ) then[127X[104X730[4X[25X>[125X [27X return 1;[127X[104X731[4X[25X>[125X [27X else[127X[104X732[4X[25X>[125X [27X return 0;[127X[104X733[4X[25X>[125X [27X fi;[127X[104X734[4X[25X>[125X [27X end,[127X[104X735[4X[25X>[125X [27X viewLabel:= [ NCurses.attrs.BOLD + NCurses.ColorAttr( "red", -1 ),[127X[104X736[4X[25X>[125X [27X "prime", NCurses.attrs.NORMAL, " power?" ],[127X[104X737[4X[25X>[125X [27X viewValue:= value -> BrowseData.ReplacedEntry( value,[127X[104X738[4X[25X>[125X [27X [ 0, 1, 2 ], [ "-", "+",[127X[104X739[4X[25X>[125X [27X [ NCurses.attrs.BOLD + NCurses.ColorAttr( "red", -1 ),[127X[104X740[4X[25X>[125X [27X true, "+",[127X[104X741[4X[25X>[125X [27X NCurses.ColorAttr( "red", -1 ), false ] ] ),[127X[104X742[4X[25X>[125X [27X sortParameters:= [ "add counter on categorizing", "yes" ],[127X[104X743[4X[25X>[125X [27X align:= "c",[127X[104X744[4X[25X>[125X [27X categoryValue:= value -> BrowseData.ReplacedEntry( value,[127X[104X745[4X[25X>[125X [27X [ 0, 1, 2 ],[127X[104X746[4X[25X>[125X [27X [ "not prime power", "prime power, not prime", "prime" ] ),[127X[104X747[4X[25X>[125X [27X ) );[127X[104X748[4X[25Xgap>[125X [27Xt3:= BrowseTableFromDatabaseIdEnumerator( smallintenum2,[127X[104X749[4X[25X>[125X [27X [ "self" ],[127X[104X750[4X[25X>[125X [27X [ "primes & prime powers", "residue mod 11",[127X[104X751[4X[25X>[125X [27X "inverse factorial" ],[127X[104X752[4X[25X>[125X [27X t -> BrowseData.HeaderWithRowCounter( t, "Small integers", n ) );;[127X[104X753[4X[25Xgap>[125X [27Xsample_session2:= Concatenation([127X[104X754[4X[25X>[125X [27X # categorize by the first column, expand categories, wait, reset[127X[104X755[4X[25X>[125X [27X nop, "scsc", nop, "X", nop, "!", "Q" );;[127X[104X756[4X[25Xgap>[125X [27XBrowseData.SetReplay( sample_session2 );[127X[104X757[4X[25Xgap>[125X [27XNCurses.BrowseGeneric( t3 );[127X[104X758[4X[25Xgap>[125X [27XBrowseData.SetReplay( false );[127X[104X759[4X[25Xgap>[125X [27XUnbind( t3.dynamic.replay );[127X[104X760[4X[32X[104X761762[33X[0;0YNow we want to consider the database as extendible, that is, we want to be763able to increase [22Xn[122X after constructing the database attributes. For that, we764use [22Xn[122X as the [10Xversion[110X value of the database id enumerator, and provide765[10Xversion[110X and [10Xupdate[110X components for all attributes.[133X766767[33X[0;0YAgain, we start the construction from scratch.[133X768769[4X[32X Example [32X[104X770[4X[25Xgap>[125X [27Xsmallintenum3:= DatabaseIdEnumerator( rec([127X[104X771[4X[25X>[125X [27X identifiers:= [ 1 .. n ],[127X[104X772[4X[25X>[125X [27X entry:= function( dbidenum, id ) return id; end,[127X[104X773[4X[25X>[125X [27X viewLabel:= "",[127X[104X774[4X[25X>[125X [27X version:= n,[127X[104X775[4X[25X>[125X [27X update:= function( dbidenum )[127X[104X776[4X[25X>[125X [27X dbidenum.identifiers:= [ 1 .. n ];[127X[104X777[4X[25X>[125X [27X dbidenum.version:= n;[127X[104X778[4X[25X>[125X [27X return true;[127X[104X779[4X[25X>[125X [27X end,[127X[104X780[4X[25X>[125X [27X ) );;[127X[104X781[4X[25Xgap>[125X [27XupdateByUnbindData:= function( attr )[127X[104X782[4X[25X>[125X [27X Unbind( attr.data );[127X[104X783[4X[25X>[125X [27X return true;[127X[104X784[4X[25X>[125X [27X end;;[127X[104X785[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum3, rec([127X[104X786[4X[25X>[125X [27X identifier:= "primes",[127X[104X787[4X[25X>[125X [27X type:= "values",[127X[104X788[4X[25X>[125X [27X name:= "IsPrimeInt",[127X[104X789[4X[25X>[125X [27X viewLabel:= "prime?",[127X[104X790[4X[25X>[125X [27X viewValue:= value -> BrowseData.ReplacedEntry( value,[127X[104X791[4X[25X>[125X [27X [ true, false ], [ "+", "-" ] ),[127X[104X792[4X[25X>[125X [27X sortParameters:= [ "add counter on categorizing", "yes" ],[127X[104X793[4X[25X>[125X [27X align:= "c",[127X[104X794[4X[25X>[125X [27X categoryValue:= value -> BrowseData.ReplacedEntry( value,[127X[104X795[4X[25X>[125X [27X [ true, false ], [ "prime", "nonprime" ] ),[127X[104X796[4X[25X>[125X [27X version:= n,[127X[104X797[4X[25X>[125X [27X update:= updateByUnbindData,[127X[104X798[4X[25X>[125X [27X ) );[127X[104X799[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum3, rec([127X[104X800[4X[25X>[125X [27X identifier:= "prime powers",[127X[104X801[4X[25X>[125X [27X type:= "values",[127X[104X802[4X[25X>[125X [27X name:= "IsPrimePowerInt",[127X[104X803[4X[25X>[125X [27X viewLabel:= "prime power?",[127X[104X804[4X[25X>[125X [27X viewValue:= value -> BrowseData.ReplacedEntry( value,[127X[104X805[4X[25X>[125X [27X [ true, false ], [ "+", "-" ] ),[127X[104X806[4X[25X>[125X [27X sortParameters:= [ "add counter on categorizing", "yes" ],[127X[104X807[4X[25X>[125X [27X align:= "c",[127X[104X808[4X[25X>[125X [27X categoryValue:= value -> BrowseData.ReplacedEntry( value,[127X[104X809[4X[25X>[125X [27X [ true, false ], [ "prime power", "not prime power" ] ),[127X[104X810[4X[25X>[125X [27X version:= n,[127X[104X811[4X[25X>[125X [27X update:= updateByUnbindData,[127X[104X812[4X[25X>[125X [27X ) );[127X[104X813[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum3, rec([127X[104X814[4X[25X>[125X [27X identifier:= "factors",[127X[104X815[4X[25X>[125X [27X type:= "values",[127X[104X816[4X[25X>[125X [27X name:= "Factors",[127X[104X817[4X[25X>[125X [27X viewLabel:= "factors",[127X[104X818[4X[25X>[125X [27X viewValue:= value -> JoinStringsWithSeparator( List( value, String ),[127X[104X819[4X[25X>[125X [27X " * "),[127X[104X820[4X[25X>[125X [27X widthCol:= 10,[127X[104X821[4X[25X>[125X [27X version:= n,[127X[104X822[4X[25X>[125X [27X update:= updateByUnbindData,[127X[104X823[4X[25X>[125X [27X ) );[127X[104X824[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum3, rec([127X[104X825[4X[25X>[125X [27X identifier:= "residue mod 11",[127X[104X826[4X[25X>[125X [27X type:= "values",[127X[104X827[4X[25X>[125X [27X create:= function( attr, id ) return id mod 11; end,[127X[104X828[4X[25X>[125X [27X viewSort:= BrowseData.SortAsIntegers,[127X[104X829[4X[25X>[125X [27X categoryValue:= res -> Concatenation( String( res ), " mod 11" ),[127X[104X830[4X[25X>[125X [27X version:= n,[127X[104X831[4X[25X>[125X [27X update:= updateByUnbindData,[127X[104X832[4X[25X>[125X [27X ) );[127X[104X833[4X[25Xgap>[125X [27XDatabaseAttributeAdd( smallintenum3, rec([127X[104X834[4X[25X>[125X [27X identifier:= "inverse factorial",[127X[104X835[4X[25X>[125X [27X type:= "pairs",[127X[104X836[4X[25X>[125X [27X data:= rec( automatic:= factorialdata( n ), nonautomatic:= [] ),[127X[104X837[4X[25X>[125X [27X isSorted:= true,[127X[104X838[4X[25X>[125X [27X categoryValue:= function( k )[127X[104X839[4X[25X>[125X [27X if k = "" then[127X[104X840[4X[25X>[125X [27X return "(no factorial)";[127X[104X841[4X[25X>[125X [27X else[127X[104X842[4X[25X>[125X [27X return Concatenation( String( k ), "!" );[127X[104X843[4X[25X>[125X [27X fi;[127X[104X844[4X[25X>[125X [27X end,[127X[104X845[4X[25X>[125X [27X version:= n,[127X[104X846[4X[25X>[125X [27X update:= function( attr )[127X[104X847[4X[25X>[125X [27X attr.data.automatic:= factorialdata( n );[127X[104X848[4X[25X>[125X [27X return true;[127X[104X849[4X[25X>[125X [27X end,[127X[104X850[4X[25X>[125X [27X ) );[127X[104X851[4X[32X[104X852853[33X[0;0YNow we can change the set of database entries by assigning a new value to854the variable [10Xn[110X, and then calling [2XDatabaseIdEnumeratorUpdate[102X ([14XA.1-7[114X).[133X855856[4X[32X Example [32X[104X857[4X[25Xgap>[125X [27Xn:= 200;;[127X[104X858[4X[25Xgap>[125X [27XDatabaseIdEnumeratorUpdate( smallintenum3 );[127X[104X859[4X[28Xtrue[128X[104X860[4X[25Xgap>[125X [27Xt4:= BrowseTableFromDatabaseIdEnumerator( smallintenum3,[127X[104X861[4X[25X>[125X [27X [ "self" ], [ "primes", "prime powers", "factors", "residue mod 11",[127X[104X862[4X[25X>[125X [27X "inverse factorial" ],[127X[104X863[4X[25X>[125X [27X t -> BrowseData.HeaderWithRowCounter( t, "Small integers", n ) );;[127X[104X864[4X[25Xgap>[125X [27XBrowseData.SetReplay( sample_session );[127X[104X865[4X[25Xgap>[125X [27XNCurses.BrowseGeneric( t4 );[127X[104X866[4X[25Xgap>[125X [27XBrowseData.SetReplay( false );[127X[104X867[4X[25Xgap>[125X [27XUnbind( t4.dynamic.replay );[127X[104X868[4X[32X[104X869870871[1XA.4 [33X[0;0YExample: An Overview of the [5XGAP[105X[101X[1X Library of Tables of Marks[133X[101X872873[33X[0;0YThe example shown in this section deals with [5XGAP[105X's Library of Tables of874Marks (the [5XTomLib[105X package [NMP13]).[133X875876[1XA.4-1 BrowseTomLibInfo[101X877878[29X[2XBrowseTomLibInfo[102X( ) [32X function879[6XReturns:[106X [33X[0;10Ynothing.[133X880881[33X[0;0YThis function shows the contents of the [5XGAP[105X Library of Tables of Marks (the882[5XTomLib[105X package, see [NMP13]) in a browse table.[133X883884[33X[0;0YThe first call may take substantial time (about [22X40[122X seconds), because the885data files of the [5XTomLib[105X package are evaluated. This could be improved by886precomputing and caching the values. Another possibility would be to call887[2XBrowseTomLibInfo[102X once before creating a [5XGAP[105X workspace. The subsequent calls888are not expensive.[133X889890[33X[0;0YThe table rows correspond to the tables of marks, one column of row labels891shows the identifier of the table. The columns of the table contain892information about the group order, the number of conjugacy classes of893subgroups, the identifiers of tables of marks with fusions to and from the894given table, and the name of the file that contains the table of marks data.[133X895896[33X[0;0YThe full functionality of the function [2XNCurses.BrowseGeneric[102X ([14X4.3-1[114X) is897available.[133X898899[4X[32X Example [32X[104X900[4X[25Xgap>[125X [27Xc:= [ NCurses.keys.ENTER ];;[127X[104X901[4X[25Xgap>[125X [27Xn:= [ 14, 14, 14 ];; # ``do nothing''[127X[104X902[4X[25Xgap>[125X [27XBrowseData.SetReplay( Concatenation([127X[104X903[4X[25X>[125X [27X "scrrsc", # categorize the list by source tables of fusions,[127X[104X904[4X[25X>[125X [27X "srdd", # choose a source table,[127X[104X905[4X[25X>[125X [27X "x", # expand the list of targets of fusions[127X[104X906[4X[25X>[125X [27X n,[127X[104X907[4X[25X>[125X [27X "!", # revert the categorization[127X[104X908[4X[25X>[125X [27X "q", # leave the mode in which a row is selected[127X[104X909[4X[25X>[125X [27X "scrrrrsc", # categorize the list by filenames[127X[104X910[4X[25X>[125X [27X "X", # expand all categories[127X[104X911[4X[25X>[125X [27X n,[127X[104X912[4X[25X>[125X [27X "!", # revert the categorization[127X[104X913[4X[25X>[125X [27X "scso", # sort the list by group order[127X[104X914[4X[25X>[125X [27X n,[127X[104X915[4X[25X>[125X [27X "!q", # revert the sorting and selection[127X[104X916[4X[25X>[125X [27X "?", # open the help window[127X[104X917[4X[25X>[125X [27X n,[127X[104X918[4X[25X>[125X [27X "Q", # close the help window[127X[104X919[4X[25X>[125X [27X "/A5", c, # search for the first occurrence of "A5"[127X[104X920[4X[25X>[125X [27X n,[127X[104X921[4X[25X>[125X [27X "Q" ) );; # and quit the browse table[127X[104X922[4X[25Xgap>[125X [27XBrowseTomLibInfo();[127X[104X923[4X[25Xgap>[125X [27XBrowseData.SetReplay( false );[127X[104X924[4X[32X[104X925926927928