Using
How a System project's scripts reach its own modules: use root.Data.Greeter, use script.Parent.Data.Greeter, a bare use Greeter, or require in a .luau file.
use root.Data.Greetermodule GreeterGreeter.Hello("Ada")The project
Notes.ssp: the module Data/Greeter.shot and the program Hello.shot.
shot new Notes.ssp
shot write Data/Greeter.shot --project Notes.ssp the module, its text on stdin
shot write Data/Types.shot --project Notes.ssp the folder's Types.shot, empty
shot write Hello.shot --project Notes.ssp the program
shot edit .shotsystem --project Notes.ssp export Main becomes export Helloshot tree --project Notes.ssp:
Notes.ssp
./ (the project)
Data/
Greeter.shot
Types.shot
Hello.shot
Main.shotshot run Notes.ssp now runs the export, Hello (One-file projects, THE EXPORT).
A module file
Data/Greeter.shot
types script.Parent.Types
doc { Greets people by name }
module Greeter = {
doc { How many people it greeted }
Count : number = 0
function Hello(name : string) : string
module.Count += 1
return "Hello, " .. name .. "!"
end
}- Line 1 is
types script.Parent.Types; the folder needs a Types.shot, even an empty one. Without it:
Notes.ssp/Data/Greeter.shot:1 types file not found: script.Parent.Types- One table of properties (
Name : Type = value) and functions; inside,moduleis the module (module.Count). - Private helpers are plain locals above the declaration (Modules).
- Class (Classes) and func (Funcs) files work the same.
- A plain Luau module has no types line and returns its table:
Data/Shout.luau
local Shout = {}
function Shout.Loud(text : string) : string
return string.upper(text) .. "!"
end
return Shoutuse root.Data.Shout reaches it too: print(Shout.Loud("hello")) prints HELLO!.
A script uses it
Hello.shot, a program script (it declares nothing):
use root.Data.Greeter
print(Greeter.Hello("Ada"))
print(Greeter.Hello("Grace"))
print(Greeter.Count .. " greeted")It checks with 0 errors and prints:
Hello, Ada!
Hello, Grace!
2 greeteduse root.Data.Greeter is short for local Greeter = require(root.Data.Greeter): the local takes the last name. root is the root instance (One-file projects, ROOT AND SCRIPT).
Every form
Each works as Hello.shot's first line:
use root.Data.Greeter | any .shot file: the path from the project's root |
use script.Parent.Data.Greeter | from the file's own folder (Hello.shot's is the root) |
local Greeter = require(root.Data.Greeter) | the same as use root.Data.Greeter |
local Greeter = require(script.Parent.Data.Greeter) | Luau's form, and the only one in a .luau file |
script is the file's own instance, script.Parent its folder.
A bare name finds the nearest file so named: the file's folder, then each folder above, never below. So use Greeter works in Data and under it:
Data/Welcome.shot
types script.Parent.Types
use Greeter
doc { The first line a new user sees }
module Welcome = {
function Line(name : string) : string
return Greeter.Hello(name) .. " Your notes are ready."
end
}Hello.shot
use root.Data.Welcome
print(Welcome.Line("Ada"))prints:
Hello, Ada! Your notes are ready.- A name no project file answers is a service:
use FileService(Services, REACH A SERVICE). - Another project:
use external "Station.ssp"(Externals).
In a .LUAU file
A .luau file has no use or root; it requires by its place in the tree. Hi.luau, at the root, made the export (export Hi):
local Greeter = require(script.Parent.Data.Greeter)
print(Greeter.Hello("Ada"))It prints Hello, Ada!. With require(root.Data.Greeter), check gives
Notes.ssp/Hi.luau:1:25 root.Data.Greeter: root is a .shot file's and a scenario's, so in a .luau file it is nil at run; a .luau file reaches its project by its place in the tree: script.Parent.Data.Greeterand the run stops:
error: Hi.luau:1: attempt to index nil with 'Data'
at Hi.luau:1Scenarios are the one .luau files with root (Scenarios).
A dot for a module, a colon for a service
A module has no self: call it with a dot, Greeter.Hello("Ada"). Greeter:Hello("Ada") gives
Notes.ssp/Hello.shot:3:7 TypeError: Expected this to be 'string', but got 'Greeter'
Notes.ssp/Hello.shot:3:21 TypeError: Argument count mismatch. Function 'Greeter.Hello' expects 1 argument, but 2 are specifiedServices, instances and what they give back take a colon: FileService:WriteAsync(path, text), child:WaitAsync() (Services, ProcessService).
The Roblox forms and their errors
The language pages' Roblox examples write @shot.Wallet.Bank: here, root.Wallet.Bank. As Hello.shot's line 1, each form below gives the error under it.
use @shot.Data.Greeter, or local Greeter = require(@shot.Data.Greeter):
Notes.ssp/Hello.shot:1 @shot is the Roblox target's: in a System project a path from the project root starts with root, like use root.Utils.Moplocal Greeter = require("./Data/Greeter"):
Notes.ssp/Hello.shot:1:17 require("./Data/Greeter"): a string require is @<Alias> from the project's header, or @shotsystem/<Service>, so a run refuses a file path; a module of this project comes by its place in the tree: use script.Parent.Data.Greeteruse Greeter at the root:
Notes.ssp/Hello.shot:1 use Greeter: no Greeter in this folder or any folder above it (use looks at each folder's own files and folders, up to the project root); it is in Data: use root.Data.Greeterimport Greeter from script.Data.Greeter, plus a TypeError per line naming Greeter:
Notes.ssp/Hello.shot:1 import only works in a Types file: move it to this folder's Types.shot (every file of the folder sees what it imports)
Notes.ssp/Hello.shot:3:7 TypeError: Unknown global 'Greeter'; consider assigning to it firstimport only brings types, in a Types.shot (Types).
shot run stops at a refused use line or string path:
error: Hello.shot:1: @shot is the Roblox target's: in a System project a path from the project root starts with root, like use root.Utils.Mop
at Hello.shot:1
error: Hello.shot:1: require("./Data/Greeter"): Notes.ssp has no external of that name (a string require is @<Alias> from the project's header, or @shotsystem/<Service>)
at Hello.shot:1require(@shot.Data.Greeter) still runs: only check refuses it.
