|
Routines and Variable Scoping |
As projects grow, it becomes essential to break code into smaller, reusable building blocks. In Sheerpower, these are called routines. They not only organize your code, but also control how variables are shared, isolated, or reset between calls.
A—Z, 0—9, _). They must begin
with a letter and include at least one underscore.
For example, do_taxes is valid, but taxes is
not. Routine names are case-insensitive. By design, Sheerpower never
uses underscores in its own keywords, so your routine names will never
collide with language features.
Global Routines: The default type. All global variables are accessible inside them.
Private Routines: Use their own variable namespace.
By default, variables declared inside are local to that
routine. If you need to access a global variable, prefix it
with main$.
Problem: In larger applications, routines may need access to shared data. However, unrestricted access to global variables introduces hidden dependencies and reduces predictability.
Solution: The main$ prefix provides
an explicit way for private, scoped, or local routines to access
global variables when necessary. At the same time, private
routines maintain an isolated namespace, making them well-suited
for a functional-style approach based on inputs, computation,
and explicit returned results.
Efficiency: Isolated routines reduce unintended side effects and eliminate unnecessary data sharing. Explicit inputs and outputs improve readability, simplify reasoning, and make code easier to test and maintain.
Takeaway: Private routines support a functional-style design, but do not enforce it. For best results:
main$ as an explicit escape from isolationScoped Routines: Similar to private routines, but
all non-static variables are cleared on entry and again on exit. Prefix
any variable with static to preserve it across
calls.
Local Routines: Logically associated with a parent routine,
local routines share the parent’s scope and can only be called
from within that routine. This allows complex logic to be broken into
smaller, named steps without cluttering the parent routine, without
parameter passing, and without runtime overhead from copying data.
Local routines are called using the local prefix before
their name and are normally declared immediately after the
end routine of their parent.
Note:
Local routines can only be called from within
private or scoped parent routines. The
compiler enforces this restriction, preventing accidental coupling
or misuse. Requiring the local prefix at the call site
also makes it immediately clear that a local routine is being
invoked, improving readability and avoiding ambiguity.
Why Local Routines Exist: As routines grow, it is natural to want to split them into smaller, clearer steps. In many environments, doing so requires stopping to decide which values should be passed, how those values should be organized, and what scope each helper should have. This extra decision-making can interrupt development flow at the very moment when clarity is most needed.
Local routines address this by allowing a routine to be split into named steps without redesigning data flow. They solve the problem by letting you organize logic into named steps while staying entirely within the same variable scope. This keeps your attention focused on the problem being solved.
Takeaway:
Local routines turn large routines into smaller,
easier-to-read and easier-to-maintain routines, without the
cognitive or runtime overhead common in nested code.
Some routines are intended to execute only once during the lifetime of a program. These are typically initialization or registration routines.
Rather than manually managing flags such as
initialized?, Sheerpower provides a
declaration-level solution:
When a routine is declared once, its body
executes only on the first call. All subsequent calls
return immediately at entry, before any body statements
execute. The routine is never re-entered after its first
execution, and any side effects occur only once.
Note: Returning values are cached from the first execution and reused on all later calls.
Problem: Initialization logic is often protected by ad-hoc flags scattered through code—cluttering it.
Solution: Declare the routine with
once. The runtime enforces single execution without the need
for code-cluttering ad-hoc flags.
Efficiency: After the first call, the routine short-circuits at entry — no body execution, no extra checks inside the routine.
Takeaway: Lifecycle intent belongs in the language, not in scattered boolean guards.
end routine.
Internally, the runtime marks the routine as executed in its control structure. Later calls short-circuit before the first statement runs.
No manual initialized? flag is required.
The declaration guarantees correctness.
(Show/Hide Sheerpower ONCE Takeaways)
once guarantees single execution per
program run.
Routines always use named parameters. Do
not prefix the call with call.
Instead, write the routine name directly, followed by
with (input) and returning (output)
parameter assignments. Named parameters eliminate positional errors and make
refactoring safer when parameter lists change.
Input parameters in the with clause are
read-only — the compiler prevents any
modifications. They are passed by reference for efficiency,
but cannot be changed within the routine. A routine may accept
up to 16 input parameters using the with clause.
Output values are specified using the returning
clause. Up to 16 values may be returned, and each returned
variable must be explicitly named in the call. Together, the
with and returning clauses allow a
maximum of 32 parameters per routine.
Output:
Sheerpower routines combine clarity, safety, and flexibility. Strong scoping rules reduce accidental variable misuse, while named parameters make code self-documenting and maintainable.
Sheerpower gives you three statements for managing execution flow within a routine without relying on exceptions, flags, or deeply nested conditionals.
exit routine — Exit the routine immediately,
returning control to the caller before reaching the routine’s
normal end.
repeat routine — Restart execution of the routine
from the beginning without resetting parameters or variables.
guard condition — Enforce a required
condition; if it is not met, the routine exits immediately.
exit routine — Early, Intentional Exit
Use exit routine when continuing execution no longer
makes sense, but the situation is not exceptional.
guard condition — Enforcing Preconditions
Use guard to make required conditions explicit and
self-documenting.
repeat routine — Controlled Retry Without
Reset
Use repeat routine when a routine must retry its logic
while retaining parameters and variable state.
guard and
exit routine
This example demonstrates how guard enforces required
inputs, while exit routine handles valid early-exit
cases without error handling or deep nesting.
Sheerpower supports generator-style routines using yield
and continue routine_name. This lets a routine suspend
execution, return to the caller, and later resume exactly where it
last yielded.
This is useful for incremental processing, streaming data, stateful iteration, and cooperative workflows where a routine produces results over time rather than all at once.
yield Worksyield causes the current routine to return immediately
to its caller.
yield.
continue routine_nameTo resume a previously yielded routine, use:
The routine_name must be the name of a routine that has
already executed a yield. Execution resumes from the
last yield point inside that routine.
yield does not reset parameters or local variables.
yield statements may appear within the same
routine.
yield
Unlike exception-based generators or hidden iterator objects in other
languages, Sheerpower’s yield and
continue statements keep control flow explicit, readable,
and deterministic.
_yield
_yield is a built-in boolean status variable that
indicates whether the most recent routine call or
continue operation exited via a yield.
_yield is true if the routine executed
a yield and can be continued.
_yield is false if the routine
completed normally and cannot be continued.
_yield is set when a routine exits and reflects the
outcome of the most recent routine call or
continue operation.
This allows callers to determine whether a yielded routine is still
active and decide whether further continue operations
are valid.
continue routine_name is valid only if that routine has
previously executed a yield and is currently suspended.
If the routine is not in a yielded state, continue
raises a runtime error.
_error and _routine
_error is always false on routine entry and becomes
true when you execute set error on; callers can
check _error after the call.
Also see Exception Handling.
Inside a routine,
_routine provides the routine's name as a string.
_).call.
Instead: routine_name with ... returning ...returning;
inputs are passed with the with clause.global — default; shares all
global variablesprivate — separate variable
namespacescoped — like private, but clears
variables on entry/exitlocal — inherits parent's scope;
callable only by parent — aids fast code segmentation_error is false on entry;
set error on marks failure for the caller to check._routine returns the current
routine's name (string) for debugging/logging.|
Hide Description
|
|
|
Enter or modify the code below, and then click on RUN |
|
Looking for the full power of Sheerpower?
Check out the Sheerpower website. Free to download. Free to use. |