Imports
Let's unravel the art of importing files and libraries in FatScript! Why? Well, because in this language you can import whenever your heart desires, simply by using a left arrow <-
.
Dot syntax
To use imports with dot syntax, project files and folders should neither start with a digit nor contain symbols.
you can specify any path you like by using literal paths
Named import
To import files, use the .fat
extension for filenames (or no extension at all). However, omit the extension in the import statement. Here's an example:
ref <- filename
if both
x
andx.fat
files exist, the latter takes precedence
For importing files from folders:
ref1 <- folder.filename
ref2 <- folder.subfolder.filename
To import all files from a folder, use the dot-underscore syntax:
lib <- folder._
Please note: only files immediately inside the folder are included using the above syntax. To include files from subfolders, explicitly mention them. Additionally, a "_.fat" file (or "_" file) inside a folder can override the dot-underscore import behavior.
starting with version
3.0.1
, slashes/
can also be used as an alternative, such asref <- folder/filename
Element access
Once imported, access elements using dot syntax:
ref1.element1
Element extraction
To extract specific elements from a named import or to avoid prepending the module name every time (e.g., lib.foo
), employ destructuring assignment:
{ foo, bar } = lib
Visibility
Named imports are resolved at the global scope, irrespective of where they are declared. This means even if you declare a named import inside a function or a local scope, it will be globally accessible.
Local import
To import within the current scope, use:
_ <- filename
Local imports, unlike named imports, dump the file content directly into the current scope. Thus, an imported method can be invoked as baz(arg)
rather than ref.baz(arg)
.
While local imports are best suited for importing types into the global scope, they should be used with caution when importing library content. Overusing local imports can lead to namespace pollution, which can make it more challenging to follow the code, because it becomes less apparent where the methods come from.
Selective local import
You also can discard elements from a local import by using destructuring assignment:
{ foo } = { _ <- lib }
the point is to avoid namespace pollution, as all the contents will be processed
Literal paths
With literal paths, you may use any filename or extension. However, note that those imports are not evaluated during bundling, but at runtime. Here's an example:
ref <- '_folder/2nd-source.other'
You can also use smart texts as literal paths:
base = 'folder'
file = 'source.xyz'
ref <- '{base}/{file}'
Keep in mind that literal paths can make your code more complex, and those imports can only be dynamically resolved, so use them sparingly.
Import policy
FatScript utilizes an "import once" strategy with an in-scope flag mechanism, automatically bypassing files that have already been imported.
Imports are generally resource-efficient. However, local imports within method bodies should be avoided as they are re-evaluated with each invocation, potentially causing memory retention.
This behavior is not classified as a bug per se, but rather a consequence of design choices in FatScript's garbage collection (GC) system. The GC's optimizations exclude nodes directly derived from source code, allowing them to evade standard mark-and-sweep procedures. As a result, local imports within methods miss out on deduplication, causing their nodes to remain resident until the program's end:
myMethod = -> {
_ <- lib # potential memory leak
...
}
Here are some strategies to address this issue:
- Relocate the import statement to the outer scope.
- Opt for a named import as an alternative.
- Reorganize the 'lib' structure to export a method.