Modules
Ghost employs a simple module system to split and organize code into self-contained files.
Every ghost file is its own module with its own scope. Importing a file into another does not explicitely merge its scope. For example, two modules can define the same top-level variable with the same name without causing any name collision.
Shared Imports
Ghost keeps track of every file it imports. Importing a module in multiple locations will not execute or load that module every time. The first encounter of the imported module will be the only time its loaded and evaluated.
Binding Variables
All top-level variables within a module are exportable. To actually import data, you may specify any number of identifiers in your import statement:
import Request, Response from "http"
The above will import and bind the values Request
and Response
from the http
module. This will make Request
and Response
available in your file.
Aliases
You may import a variable under a different name using as
:
import str as isString from "helpers"
Import an entire module's contents
To import every value from a module, you may use *
:
import * from "helpers"
Cyclic Imports
Cyclic imports for the most part are "supported" by Ghost, though they should still be considered a code smell if you ever come across them. Because Ghost keeps track of the modules it imports, it's effectively able to short-circuit itself on cyclic imports:
// main.ghost
import "a";
// a.ghost
print("start a");
import "b";
print("end a");
// b.ghost
print("start b");
import "c";
print("end b");
// c.ghost
print("start c");
import "a";
print("end c");
When running the above program, you'll find that it prints the correct output and does not get stuck in an infinite loop:
start a
start b
start c
end c
end b
end a
Importing Side Effects
Import an entire module for side effects only, without importing anything. This runs the module's global code, but doesn't actually import any values.
import "beverages"
This will evaluate the module and run it, but it will not bind any new variables.
Introducing An Example
To demonstrate the usage of modules, we're going to show a very simple example below.
Basic Example Structure
In our example, we have the file structure below:
main.ghost
modules/
functions.ghost
variables.ghost
main.ghost
import * from "modules/functions"
import * from "modules/variables"
print("Program loaded.")
add(one, two)
greet(hello)
functions.ghost
function add(a, b) {
print(a + b)
}
function greet(message) {
print(message)
}
variables.ghost
one = 1
two = 2
hello = "Hello, world!"
While this is a very rudimentary example, it showcases how simple it is to load in modules. Modules are nothing more than other Ghost files, and can be located anywhere within your program. We chose to put our modules in a modules
directory, but you don't have to do this.