I would like to represent a kind of class table (CT) as a singleton in Rascal, so that some transformations might refer to the same CT. Since not all transformations need to refer to the CT (and I prefer not to change the signature of the existing transformations), I was wondering if it is possible to implement a kind of singleton object in Rascal.
Is there any recommendation for representing this kind of situation?
Edited: found a solution, though still not sure if this is the idiomatic Rascal approach.
module lang::java::analysis::ClassTable
import Map;
import lang::java::m3::M3Util;
// the class table considered in the source
// code analysis and transformations.
map[str, str] classTable = ();
/**
* Load a class table from a list of JAR files.
* It uses a simple cache mechanism to avoid loading the
* class table each time it is necessary.
*/
map[str, str] loadClassTable(list[loc] jars) {
if(size(classTable) == 0) {
classTable = classesHierarchy(jars);
}
return classTable;
}
Two answers to the question: "what to do if you want to share data acros functions and modules, but not pass the data around as an additional parameter, or as an additional return value?":
public int myGlobalInt = 666;
This works for all kinds of (complex) data, including class tables. Use this only if you need shared state of the public variable.@memo
function is a way to provide fast access to shared data in case you need to share data which will not be modified (i.e. you do not need shared state): @memo int mySharedDataProvider(MyType myArgs) = hardToGetData();
. The function's behavior must not have side-effects, i.e. be "functional", and then it will never recompute the return value for earlier provided arguments (instead it will use an internal table to cache previous results).