Appendix In order to deal with duplicate declarations and implementations of a global function glob, the final sections of the library files oper.g and global.g have been modified as shown below.

There are three changes: The lists GLOBAL_REDECLARATION_LIST, GLOBAL_REINSTALLATION_LIST and GLOBAL_REDECLARATION_COUNT are initialized. Functions AllowGlobalRedeclaration and AllowGlobalReinstallation are added. The former adds function names (as strings) to the list GLOBAL_REDECLARATION_LIST, while the latter adds the functions themselves to the list GLOBAL_REINSTALLATION_LIST. A conditional clause is inserted into the implementation of the functions DeclareGlobalFunction and InstallGlobalFunction which prevent their application to glob a second time, but ensures a first application.

The additional and modified code in oper.g is listed here.
############################################################################# ## #F AllowGlobalRedeclaration( <list> ) . . function(s) may be declared twice #F AllowGlobalReinstallation( <list> ) . . . . . . and implemented twice ## BIND_GLOBAL( "GLOBAL_REDECLARATION_LIST", ShareSpecialObj([], "GLOBAL_REDECLARATION_LIST") ); BIND_GLOBAL( "GLOBAL_REINSTALLATION_LIST", ShareSpecialObj([], "GLOBAL_REINSTALLATION_LIST") ); BIND_GLOBAL( "GLOBAL_REDECLARATION_COUNT", ShareSpecialObj([], "GLOBAL_REDECLARATION_COUNT") ); BIND_GLOBAL( "AllowGlobalRedeclaration", function( arg ) local L, pos, name, count; ## form the arguments into a list L if LEN_LIST(arg) = 1 then if IS_STRING_REP( arg[1] ) then L := arg; elif IS_LIST( arg[1] ) then L := arg[1]; else L := [ ]; fi; else L := arg; fi; for name in L do ## avoid duplicate entries in GLOBAL_REDECLARATION_LIST pos := POS_LIST_DEFAULT( GLOBAL_REDECLARATION_LIST, name, 0 ); if ( pos = fail ) then ADD_LIST( GLOBAL_REDECLARATION_LIST, name ); ## has name been declared already? if ISBOUND_GLOBAL( name ) then count := 1; else count := 0; fi; ADD_LIST( GLOBAL_REDECLARATION_COUNT, count ); fi; od; end ); BIND_GLOBAL( "AllowGlobalReinstallation", function( arg ) local L, oper, posd, posi, name; ## form the arguments into a list L if LEN_LIST(arg) = 1 then if IS_FUNCTION( arg[1] ) then L := arg; elif IS_LIST( arg[1] ) then L := arg[1]; else L := [ ]; fi; else L := arg; fi; for oper in L do ## avoid duplicate entries in GLOBAL_REINSTALLATION_LIST posi := POS_LIST_DEFAULT( GLOBAL_REINSTALLATION_LIST, oper, 0 ); if ( ( posi = fail ) and IS_FUNCTION( oper ) ) then ## check that the two lists are consistently ordered posi := LEN_LIST( GLOBAL_REINSTALLATION_LIST ) + 1; name := NAME_FUNC( oper ); posd := POS_LIST_DEFAULT( GLOBAL_REDECLARATION_LIST, name, 0 ); if ( posd = posi ) then ADD_LIST( GLOBAL_REINSTALLATION_LIST, oper ); else Error( "redeclaration and reinstallation lists inconsistent" ); fi; fi; od; end ); ############################################################################# ## #F DeclareGlobalFunction( <name>, <info> ) . . create a new global function #F InstallGlobalFunction( <oper>, <func> ) ## ## Global functions of the &GAP; library must be distinguished from other ## global variables (see <C>variable.g</C>) because of the completion ## mechanism. ## BIND_GLOBAL( "GLOBAL_FUNCTION_NAMES", ShareSpecialObj([], "GLOBAL_FUNCTION_NAMES") ); BIND_GLOBAL( "DeclareGlobalFunction", function( arg ) local pos, count, name; name := arg[1]; ## special case: redeclaration is permitted so increment count for 'name' if ( name in GLOBAL_REDECLARATION_LIST ) then pos := POS_LIST_DEFAULT( GLOBAL_REDECLARATION_LIST, name, 0 ); count := GLOBAL_REDECLARATION_COUNT[pos] + 1; GLOBAL_REDECLARATION_COUNT[pos] := count; ## if already declared then there is nothing to do if ISBOUND_GLOBAL( name ) then return; fi; fi; atomic GLOBAL_FUNCTION_NAMES do ADD_SET( GLOBAL_FUNCTION_NAMES, IMMUTABLE_COPY_OBJ(name) ); od; BIND_GLOBAL( name, NEW_OPERATION_ARGS( name ) ); end ); BIND_GLOBAL( "InstallGlobalFunction", function( arg ) local oper, info, func, pos; if LEN_LIST(arg) = 3 then oper := arg[1]; info := arg[2]; func := arg[3]; else oper := arg[1]; func := arg[2]; fi; if IS_STRING( oper ) then oper := VALUE_GLOBAL( oper ); fi; ## special case: reinstallation is permitted so check declaration number if ( oper in GLOBAL_REINSTALLATION_LIST ) then pos := POS_LIST_DEFAULT( GLOBAL_REINSTALLATION_LIST, oper, 0 ); if ( GLOBAL_REDECLARATION_COUNT[pos] >= 2 ) then ## there have been 2 declarations so this is a repeat installation return; fi; fi; atomic readonly GLOBAL_FUNCTION_NAMES do if NAME_FUNC(func) in GLOBAL_FUNCTION_NAMES then Error("you cannot install a global function for another global ", "function,\nuse `DeclareSynonym' instead!"); fi; INSTALL_METHOD_ARGS( oper, func ); od; end );

For functions installed directly using BIND_GLOBAL lists GLOBAL_REBINDING_LIST and GLOBAL_REBINDING_COUNT are used, and the function AllowGlobalRebinding added. The additional and modified code in global.g is listed here.
GLOBAL_REBINDING_LIST := [ ]; GLOBAL_REBINDING_COUNT := [ ]; ############################################################################# ## #F BIND_GLOBAL ( <name>, <val> ) . . . . . .sets a global variable 'safely' ## ## BIND_GLOBAL ( <name>, <val> ) sets the global variable named by ## the string <name> to the value <val>, provided it was previously ## unbound, and makes it read-only. This is intended to be the normal ## way to create and set "official" global variable (such as ## Operations and Categories) ## BIND_GLOBAL := function( name, val) local pos, count; ## special case: rebinding is permitted so increment count for 'name' if ( name in GLOBAL_REBINDING_LIST ) then pos := POS_LIST_DEFAULT( GLOBAL_REBINDING_LIST, name, 0 ); count := GLOBAL_REBINDING_COUNT[pos] + 1; GLOBAL_REBINDING_COUNT[pos] := count; ## if already bound then there is nothing to do if ISBOUND_GLOBAL( name ) then return; fi; fi; if not REREADING and ISBOUND_GLOBAL( name ) then if (IS_READ_ONLY_GLOBAL(name)) then Error("BIND_GLOBAL: variable `", name, "' must be unbound"); else Print("#W BIND_GLOBAL: variable `", name,"' already has a value\n"); fi; fi; ASS_GVAR(name, val); MAKE_READ_ONLY_GLOBAL(name); return val; end; ############################################################################# ## #F AllowGlobalRebinding( <list> ) . . function(s) may be BIND_GLOBAL'ed twice ## BIND_GLOBAL( "AllowGlobalRebinding", function( arg ) local L, pos, name, val; ## form the arguments into a list L if LEN_LIST(arg) = 1 then if IS_STRING_REP( arg[1] ) then L := arg; elif IS_LIST( arg[1] ) then L := arg[1]; else L := [ ]; fi; else L := arg; fi; for name in L do ## avoid duplicate entries in GLOBAL_REBINDING_LIST pos := POS_LIST_DEFAULT( GLOBAL_REBINDING_LIST, name, 0 ); if ( pos = fail ) then ADD_LIST( GLOBAL_REBINDING_LIST, name ); ## has 'name' been declared already? if ISBOUND_GLOBAL( name ) then val := 1; else val := 0; fi; ADD_LIST( GLOBAL_REBINDING_COUNT, val ); fi; od; end );