A global environment/context management system for Scryer Prolog providing key-value metadata storage one level of abstraction above the blackboard.
This library provides a clean interface for managing global state in Prolog programs using association trees (AVL trees) backed by the blackboard. It offers:
- Global persistent storage - Changes persist across backtracking
- Backtrackable local storage - Changes roll back on backtracking
- Type-safe reified predicates - Use
if_/3for conditional logic without cuts - Once-only initialization - Prevent accidental double initialization
- Key existence checking - Efficiently check for key presence
bakage.pl install environmentCopy environment.pl to your project's library directory or ensure it's in your Scryer Prolog load path.
library(reif)- Reified predicates for conditional logiclibrary(assoc)- Association trees (AVL trees)library(iso_ext)- ISO extensions including blackboard predicates
?- use_module(library(environment)).
% Set global values (persistent across backtracking)
?- env_set_global(username, 'Alice').
true.
?- env_set_global(counter, 42).
true.
% Retrieve values
?- env_key_val(username, User).
User = 'Alice'.
% Check if key exists (reified)
?- env_check_flag_t(username, T).
T = true.
% Set local value (backtrackable)
?- env_set_local(temp, 'temporary'), env_key_val(temp, V).
V = 'temporary'.
% Initialize once (prevents double initialization)
?- env_set_global_once(config_loaded, true).
true.
?- env_set_global_once(config_loaded, false).
ERROR: runtime_error(env_set_global_once)Retrieve the current global environment as an association tree.
Replace the entire global environment (persistent).
Replace the entire global environment (backtrackable).
Set a key-value pair globally (persistent across backtracking).
Set a flag (key with value true) globally.
Set a key-value pair only if it doesn't exist. If it exists with a different value, throws an error.
Set a flag only once. Throws error if already set with different value.
Set a key-value pair locally (backtrackable).
Set a flag locally (backtrackable).
Retrieve value for a key. Throws key_error if key doesn't exist.
?- env_set_global(name, 'Bob'), env_key_val(name, N).
N = 'Bob'.Retrieve value for a key, or unify with NotFound if key doesn't exist.
?- env_key_val_notfound(missing_key, V, default).
V = default.Check if a flag exists (deterministic success/failure).
Reified version: unifies Truth with true or false.
?- env_set_global_flag(debug),
env_check_flag_t(debug, T1),
env_check_flag_t(missing, T2).
T1 = true,
T2 = false.Check if key exists with specific value (deterministic).
Reified version of key-value check.
Alias for env_check_key_val_t/3.
Assert that a flag exists (throws error if missing).
Remove a key from the environment (persistent).
Remove a key from the environment (backtrackable).
% Initialize configuration once
init_config :-
env_set_global_once(db_host, 'localhost'),
env_set_global_once(db_port, 5432),
env_set_global_flag_once(config_loaded).
% Access configuration
get_db_connection(Host, Port) :-
env_key_val(db_host, Host),
env_key_val(db_port, Port).% Enable/disable features
enable_feature(Feature) :-
env_set_global_flag(Feature).
disable_feature(Feature) :-
env_remove(Feature).
% Check if feature is enabled
feature_enabled(Feature) :-
env_check_flag(Feature).
% Conditional execution
maybe_log(Message) :-
env_check_flag_t(logging_enabled, T),
if_(T=true,
format('LOG: ~w~n', [Message]),
true
).% Use local state that backtracks
process_with_context(Data, Result) :-
env_set_local(current_data, Data),
process_step_1,
process_step_2,
env_key_val(result, Result).% Increment counter
increment_counter(Name) :-
env_key_val_notfound(Name, Current, 0),
Next is Current + 1,
env_set_global(Name, Next).
% Usage
?- increment_counter(requests), increment_counter(requests).
true.
?- env_key_val(requests, Count).
Count = 2.The environment is initialized exactly once using term_expansion/2. The first time the module is loaded, it creates an empty association tree and stores it in the blackboard under global_context.
This library extensively uses reified predicates from library(reif) for conditional logic without cuts. This enables pure, declarative programming with backtracking-friendly conditionals.
- All operations are O(log n) due to the underlying AVL tree implementation
- Key lookups are efficient even with thousands of entries
- Reified key existence checking avoids expensive exception handling
BSD-2-Clause (compatible with Scryer Prolog standard libraries)
Jay
0.1.0