LIBRARY

<< Click to Display Table of Contents >>

Navigation:  Gekko User Manual > Gekko statements >

LIBRARY

Previous pageReturn to chapter overviewNext page

The LIBRARY statement can be used to load and handle libraries of user-defined functions, procedures or external files. A Gekko library is basically a .zip-file containing user-defined functions/procedures inside Gekko program files (.gcm), and data files inside the \data subfolder of the zip file (data files can be for instance table or plot schemas, list files, databanks, etc.).

 

Don't be scared

Gekko libraries are designed to be as easy as possible to develop and use. If the user knows how to zip one or more program .gcm files into a zip file, that will be enough to create a library. There is no compiling, packaging, registering, uploading, installation, etc. Just zip the file(s), and the library is ready to use and share, and because of caching and so-called lazy loading, a LIBRARY statement normally executes very quickly, even if the library is large.

 

Libraries are organized in a hierarchy, similar to how the databanks hierarchy works. There is a special kind of library always available: the so-called Local library (empty when Gekko starts up). The Local library stores all "normal" functions/procedures, defined in a normal .gcm program file (or the statement prompt). With the LIBRARY statement, additional libraries can be loaded from library files, and when a function f() or a procedure f is called, Gekko searches for it in the hierarchical list of loaded libraries. If you need to be sure that a function/procedure is taken from a particular library, you may use colon (:) to indicate the library, for instance lib1:f(x). The Local library is always searched first in the library hierarchy.

 

Inside the library .zip file, you may organize your .gcm files (containing functions/procedures) as you please, but note that libraries operate with the special subfolders \data and \meta. Gekko will not look for .gcm files with functions/procedures inside these folders, which are used for possible data files and/or meta information (descriptions etc.). If you put for instance a file data.csv in the subfolder \data of the library lib1.zip, you may subsequently use read <csv> lib1:data.csv (or just read <csv> data.csv;), and Gekko will find the file, provided that the library is loaded (such library files are read-only). Note that when referring to a library with colon (:), backslashes should never be used.

 

 

Syntax

 

library lib1, lib2, ... ;           //Load these files/libraries

library lib1 as l1, lib2 as l2, ... ; //Alias names

library <close> lib1, lib2, ... ;     //Close libraries (not possible for the Local library).

library <close> *;                   //Close all libraries (except Local library).

library <clear> local;               //Clear the Local library.

library ?;                           //Show info about loaded libraries.

 

To refer to a function/procedure from a particular library, use colon (:). For instance lib1:f() or lib1:f. When loading a library with LIBRARY, if no file path is provided, Gekko will look for library files in the working folder. If not found there, it will additionally look in the folders designated with option folder command = ..., option folder command1 = ..., and option folder command2 = ..... This is where Gekko also looks for normal .gcm files, cf. RUN.

 


 

Examples

 

As noted above, Gekko libraries are simply a collection of .gcm files (and possibly other files) stored inside a .zip file. You may use any folder structure inside the .zip file: this structure has no significance (apart from the folder names \data and \meta being specially treated). Try creating the following two .gcm files (you may use EDIT to do that, or use some other text editor). After the files are created, pack them into individual zip files (you may alternatively download the two .zip files here and here).

 

lib1.zip, containing lib1.gcm
 

//lib1.gcm
function string f1(); 
  return 'lib1'; 
end;

 

lib2.zip, containing lib2.gcm
 

//lib2.gcm
function string f1(); 
  return 'lib2'; 
end;
 
function string f2(); 
  return f1(); 
end;

 

The two zip-files, lib1.zip and lib2.zip, should be located in the working folder. Now, we can try out the libraries:

 

reset;
library lib1;             //loads lib1.zip
prt f1();                 //prints 'lib1'
library <close> lib1;     //closes the library
prt f1();                 //error
library lib1;             //(re)load it
library lib2;             //load lib2.zip, too. Library list is now Local, lib1, lib2
library ?;                //Info on libraries and their contents.
prt f1();                 //prints 'lib1' because lib1 is before lib2.
prt lib2:f1();            //prints 'lib2' because lib2 is denoted with colon.
prt f2();                 //prints 'lib2' because own library f1() version has priority
function string f1(); return 'Local'; end;
prt f1();                 //prints 'Local', because local functions have priority
prt f2();                 //still prints 'lib2' because own library f1() version has priority

 

When both lib1.zip and lib2.zip are loaded, lib1 is before lib2 in the hierarchical list of loaded libraries. When f1() is called, Gekko first looks in Local (empty), and then in lib1, where it is found. Therefore, prt f1(); prints 'lib1', because it is the version of f1() in lib1 that gets called. When instead lib2:f1() is used to denote the library explicitly, Gekko locates f1() in lib2 instead. In the last line above, f2() is called. This function only exists in lib2, and the function basically just calls f1(). When f1() is called from within f2(), Gekko first looks for f1() in the same library as the calling function resides in (namely lib2). Therefore, prt f2(); prints 'lib2'. As shown with the function statement above, if you define f1() locally, without putting it inside a library zip file, it will take priority over other versions of f1().

 

The library ?; statement will print the following on screen:

 

clip0136

If you for instance click more regarding lib2, its functions are shown:

clip0137    

If you click a function, its contents (Gekko code) is shown in the output tab.

 


 

External files inside libraries

 

As mentioned above, you may also put other kinds of data files inside a library. Such external files must be placed inside a \data subfolder inside the .zip file. Such files will be read-only and can be for instance table or plot schemas (.gtb/.gpt), Gekko databanks, data files, etc. In general, when encountering a filename without a path, Gekko will first look for the file in the working folder, and next in folders stated with option folder ... ;. If not present there, and if libraries are loaded, Gekko will also look for the file inside the \data subfolder of the libraries.

 

For instance, consider the plot schema file (setting the plot style to show histograms):

 

pretty.gpt

 

<gekkoplot>
  <type>boxes</type>
</gekkoplot>

 

Try storing this as a file pretty.gpt, and put it inside a \data subfolder of a zip-file called lib3.zip (or download the zip file from here). Next, place the zip file in your working folder, and try the following:

 

reset;
time 2021 2025;
x1 = 2, 4, 3, 5, 4;
x2 = 3, 6, 5, 7, 8;
plot x1, x2;                     //normal lines
library lib3;                    //loads lib3.zip
plot <using=pretty.gpt> x1, x2;  //boxes/histograms
option plot using = pretty.gpt;  //set global plot schema
plot x1, x2;                     //boxes/histograms

 

If you want to be completely sure that a file originates from a particular library, you may prefix the library name like lib3:pretty.gpt. Inside the \data folder of lib3.zip, you may place pretty.gpt as you please. Examples of file types that can be stored in the \data subfolder: databanks, data files, listfiles, model files, program files, R/Python files, menu browser files, table files, plot files, download definitions (.json), etc.

 


 

Difference between the Local library and loaded libraries

 

As mentioned above, external libraries are loaded in a lazy fashion, that is, the functions/procedures inside the library are not actually parsed and compiled, until they are called. Therefore, syntax errors in a function or procedure definition do not show up immediately, in contrast to functions/procedures defined in a normal .gcm file. Normal functions/procedures end up in the Local library, which is always first in the hierarchical list of loaded libraries. The Local library cannot be closed, but it can be cleared with library <clear> local;. The Local library never contains external files, only functions and procedures.

 


 

Strategy when developing a library

 

If you are developing a library, you may proceed following these steps:

 

1.Define the function/procedure in a normal .gcm file (for instance called lib.gcm).

2.Run the .gcm file with run lib.gcm;, and fix any syntax errors. (If incomprehensible errors are encountered, you may try to out-comment the FUNCTION statement and corresponding END statement for better error messages).

3.When lib.gcm has no more syntax errors, try calling and testing the function/procedure from the statement prompt. This will reveal possible run-time errors.

4.If this works as expected, you may put the function/procedure into a library zip file: zip lib.gcm into the zip file lib.zip. Try issuing the statement library lib;, and try subsequently to call the function/library again.

5.Later on, you may need to change the function/procedure inside lib.zip. Debugging from within a library zip file may be a bit confusing, because syntax errors do not show up at once, but first when the function/procedure is called. But you may always unpack the .gcm file inside the .zip file and try it out directly with run lib.gcm;, essentially returning to step (2) above. When the file is error-free and tested, re-zip it back into lib.zip.

 

 


 

Private functions/procedures/files

 

If the library lib1 contains a function f(), and this function calls a function g(), Gekko will first look for g() in lib1 (similarly regarding procedures and external files). In this sense, a library has a concept of "locality".

 

If you need further encapsulation to guard against naming ambiguities, there are the following possibilities:

 

Private names: After loading a library, per default all of its functions, procedures and external files will be available from outside of the library. If you do not want some helper functions/procedures/files to be accessible (exposed) for use from outside of the library itself, you may prefix the name of the function/procedure/file with __ (double underscore) to ensure privateness.

'This' keyword: Inside a library function/procedure, you may use this: prefix on function/procedure/file names to refer to the library itself (guarding against bugs if the function/procedure/file does not exist in the library, but accidentally exists somewhere else).

 

 


 

How does this compare to R/Python packages?

 

A Gekko library is similar to a R or Python package. In R, packages are typically first installed with syntax like install.packages("lib1"), and in Python with syntax like pip install "lib1". After installation, in R the package is loaded with library(lib1), and in Python with import lib1. Gekko skips the installation part and only performs loading, so in Gekko, the statement library lib1; is comparable to library(lib1) in R or import lib1 in Python. Gekko libraries are intentionally simpler to create than their package counterparts in R and Python. Anyone capable of putting a function or procedure into a .gcm file and zip this file should be able to create a Gekko library!

 


 

Notes and details

 

For user-defined functions and procedures, beware that it is not advised to use the same name as an in-built Gekko function or statement name (in that case, the in-built version always takes precedence, unless an explicit library name is designated with colon :). You may encounter the problem that an new Gekko version uses the same function or statement name as your user-defined function/procedure. In that case, it is advised to rename your user-defined function/procedure (Gekko will issue warnings in such cases).

 

The names of the .gcm files outside of the \data subfolder of the zip file have no significance. Some people prefer to store the function f() inside a file called f.gcm, whereas others store all functions/procedures inside the same large .gcm file. The .gcm files outside of the \data subfolder of a zip file may only contain functions or procedures, nothing else (and nested functions/procedures are not legal). When referring to functions/procedures/files inside a library file, the internal folder structure of the zip file has no significance (other than external files reside in the \data subfolder, and functions/procedures do not). You may define different versions of the same function or procedures, provided that they have different numbers of arguments (so-called overloads).

 

Libraries are loaded in a lazy fashion. So when referencing a library via a statement like library lib1;, the functions/procedures inside lib1.zip are not actually parsed and compiled, until a particular function/procedure from lib1.zip is called. In order for LIBRARY to read a library .zip file as fast as possible, the statement uses text heuristics to locate the functions/procedures inside the .gcm files of the .zip file. The heuristics are mostly a question of locating the FUNCTION or PROCEDURE statements and using these to cut the .gcm file into parts corresponding to different functions/procedures. If a library function/procedure fails mysteriously, try to RUN the unzipped .gcm file normally, too see if the library heuristics are to blame.

 

Library names must be of length > 1, because libraries can also be used to store external files. The length restriction is to avoid the possibility of storing for instance a pretty.gpt schema file for plots inside a c.zip file, and later refer to the schema file with c:pretty.gpt. This would be confusing, since c: could be a drive letter. You cannot use the following names as library names: Local, Global, this, null, or any name that begins with Gekko.

 

Beware that functions/procedures in a zip library lib1 have a sense of "locality": if function f() from lib1 calls function g(), Gekko will first look in lib1 for g(). Similarly for files: if function f() from lib1 uses a file data.csv, Gekko will first look in the \data folder of lib1 for the file. You may use the special keyword this as library name to be completely sure that a library function or procedure only may use its own functions/procedures/files. For instance inside the function f(), you may call the function this:g() or use the file this:data.csv. Since per default a library function or procedures first looks in its own library for a function/procedure/file, this: is mostly used to guard against the following: consider a library function f() that uses another library function g() from the same library. This works fine, but then someone deletes g() from the library by accident. This would typically result in an error, but what if -- by coincidence -- g() is defined in the Local library or in some other library? Using this: guards against that possibility.

 

An even more restrictive option for library functions/procedures is to prefix the names with double underscore (__), which makes them private (non-accessible from outside of the library). In that case, f() of the library lib1 could call the private function __g() (also from lib1), but this function is not callable from outside of lib1. Regarding external files in the \data subfolder of the library lib1, you may follow the same convention and prefix the file names with __. (these files will not be accessible from outside of the library lib1). Functions/procedures/files with prefix __ are typically helper functions/files that the user does not want to expose for general use.

 

If your library lib1 uses/depends upon the library lib2, it is safest to refer to the components of lib2 with colon. So a function f() from lib1 may load the library lib2 (with library lib2;, possibly first checking if it is already open with if(isLibraryLoaded('lib2')), and then the function g() from lib2 can be called with lib2:g() to make sure that g() is really from that library.

 

Instead of storing Gekko statement lines in an external .gcm file inside the \data subfolder of a given library, consider storing the same lines as a procedure in the non-\data part of the library.

 

Note that Gekko supports "zip paths", so that in principle you may "manually" refer directly to a file inside a zip file. So using a file name like lib1.zip\data\pretty.gpt is possible and will work without loading lib1.zip as a library (using a zip path, Gekko will automatically extract pretty.gpt from inside of lib1.zip). Still, loading the .zip file as a library in such cases is typically more convenient.

 


 

Related options

 

OPTION folder command = [empty];

OPTION folder command1 = [empty];

OPTION folder command2 = [empty];

OPTION folder working = [empty];

 


 

Related statements

 

FUNCTION, PROCEDURE, RUN