Optional: move the quiz helper into a module
ASPL 0.7.0 · Current release
Export the answer-checking helper, call it through a native module and repair a private reference.
On this page
What you will learn
This optional Native only lesson moves the quiz's answer-checking helper into answers.aspl, explicitly exports it and calls it through the answers module name. Keep the completed one-file browser quiz and its original draft.
Before you begin
Understand the completed quiz and finish install and run locally. Select native ASPL 0.7.0. The browser does not load user source modules; adding answers.aspl as a browser virtual run file does not enable import. Broader rules are in the source-module guide and reference.
Move and export the helper
Keep Question, its list, the counters, parsing and summary in the root. Adapt is_correct to accept the expected number instead of a Question, so its public signature needs only scalar types. The root passes question::answer. Remove the old helper from the root and save this complete English helper as answers.aspl:
Illustrative fragment
share fn is_correct(expected: i64, answer: i64) -> bool {
return answer matches expected;
}Save the matching Arabic helper as إجابات.لبات. It performs the same operation:
Illustrative fragment
شارك دالة هل_صحيح(متوقع: ص64, جواب: ص64) -> منطقي {
أرجع جواب يطابق متوقع.
}Declarations are private by default. share / شارك makes this helper accessible to the importing root. Arabic sources use Arabic function, variable and field names; English sources use English names. Changing the reading locale preserves the chosen source variant.
Import and call from the root
At the top of the root, import answers.aspl as answers; / استورد إجابات.لبات بسم إجابات. loads the source file relative to the root file and binds the namespace answers. Replace the former call with answers::is_correct(question::answer, parsed::value) / إجابات::هل_صحيح(السؤال::جواب, محلل::قيمة) inside the parsing-success branch.
Importing source executes no code. The helper runs only when the root calls it. The root alone has start_main / ابدأ_الرئيسية; the helper file has no entry. A source module is a local source file, distinct from a supplied library such as core::http and from browser run data.
Download the root and its matching helper below into a new directory. Use main.aspl with answers.aspl for English, or الرئيسية.لبات with إجابات.لبات for Arabic. Keep the source variants in separate directories. The catalog shows only those two supplied variants, with exact bytes, source identity and release provenance. There are no data assets. The complete root preserves all five questions and the one-file input/scoring behavior.
Execution: Native only · ASPL 0.7.0
- Native only. Select ASPL 0.7.0. Download the root and its matching answers.aspl into one directory. Keep each vocabulary and the private/exported examples in separate directories. No data files are required.
Input lines: ["5","5","12","4","15"]
Arabic source · Required source modules, keep each variant in a separate directory:
English source · Required source modules, keep each variant in a separate directory:
import answers.aspl as answers;
record Question { prompt: string, answer: i64 }
fn summary(label: string, correct: i64, answered: i64, total: i64) -> unit {
print(label + ". Correct: " + format_i64(correct) + "; answered: " + format_i64(answered) + "; total: " + format_i64(total) + ".\n");
}
fn start_main() -> i64 {
let questions: list<Question> = [
Question { prompt: "2 + 3?", answer: 5 },
Question { prompt: "9 - 4?", answer: 5 },
Question { prompt: "3 * 4?", answer: 12 },
Question { prompt: "12 / 3?", answer: 4 },
Question { prompt: "7 + 8?", answer: 15 }
];
let total: i64 = length(questions);
var index: i64 = 0;
var answered: i64 = 0;
var correct: i64 = 0;
print("Quiz: " + format_i64(total) + " questions. Type q to stop.\n");
while (index < total) {
let question: Question = questions[index];
print("Question " + format_i64(index + 1) + "/" + format_i64(total) + ": " + question::prompt + " ");
let line: string = read_line();
if (line matches "q") {
summary("Stopped early", correct, answered, total);
return 0;
}
let parsed: result<i64> = parse_i64(line);
if (parsed::ok) {
if (answers::is_correct(question::answer, parsed::value)) {
print("Correct.\n");
correct = correct + 1;
} else {
print("Wrong. Expected " + format_i64(question::answer) + ".\n");
}
answered = answered + 1;
index = index + 1;
} else {
print("Retry: " + parsed::error::code + ". Use ASCII digits, for example 5, or q.\n");
}
}
summary("Completed", correct, answered, total);
return 0;
}
Follow the Linux instructions to run this example. Download the source to keep a copy.
Download main.asplExpected outcomes
{
"native": {
"check": 0,
"status": 0,
"output": "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 5; answered: 5; total: 5.\n"
}
}Predict, check and run
From the English pair's directory:
aspl check main.aspl
aspl run main.aspl
echo $?For the Arabic pair, use these exact root commands in its separate directory:
aspl check الرئيسية.لبات
aspl run الرئيسية.لبات
echo $?Predict the output for 5, 5, 12, 4, 15. Check succeeds with status 0 and no output; Run prints five Correct. lines and Completed. Correct: 5; answered: 5; total: 5. with a final newline and status 0, without a sixth read. With 12x, 6, q, the first question retries, the wrong number advances and early stop reports zero correct, one answered and total five. EOF still traps with input-exhausted; browser Stop remains cancellation in the one-file version. Moving the helper changes neither scoring nor input/output/status concepts.
See a private reference fail
Predict what happens without share. The separate complete failed pair below has the same root and a private is_correct. Save it in its own directory, separate from the exported pair. Required files appear before the root source. Its check and run both fail with status 1, diagnostic private-member and no quiz output or input read.
Execution: Native only · ASPL 0.7.0
- Native only. Select ASPL 0.7.0. Download the root and its matching answers.aspl into one directory. Keep each vocabulary and the private/exported examples in separate directories. No data files are required.
Input: No input lines are required.
Arabic source · Required source modules, keep each variant in a separate directory:
English source · Required source modules, keep each variant in a separate directory:
import answers.aspl as answers;
record Question { prompt: string, answer: i64 }
fn summary(label: string, correct: i64, answered: i64, total: i64) -> unit {
print(label + ". Correct: " + format_i64(correct) + "; answered: " + format_i64(answered) + "; total: " + format_i64(total) + ".\n");
}
fn start_main() -> i64 {
let questions: list<Question> = [
Question { prompt: "2 + 3?", answer: 5 },
Question { prompt: "9 - 4?", answer: 5 },
Question { prompt: "3 * 4?", answer: 12 },
Question { prompt: "12 / 3?", answer: 4 },
Question { prompt: "7 + 8?", answer: 15 }
];
let total: i64 = length(questions);
var index: i64 = 0;
var answered: i64 = 0;
var correct: i64 = 0;
print("Quiz: " + format_i64(total) + " questions. Type q to stop.\n");
while (index < total) {
let question: Question = questions[index];
print("Question " + format_i64(index + 1) + "/" + format_i64(total) + ": " + question::prompt + " ");
let line: string = read_line();
if (line matches "q") {
summary("Stopped early", correct, answered, total);
return 0;
}
let parsed: result<i64> = parse_i64(line);
if (parsed::ok) {
if (answers::is_correct(question::answer, parsed::value)) {
print("Correct.\n");
correct = correct + 1;
} else {
print("Wrong. Expected " + format_i64(question::answer) + ".\n");
}
answered = answered + 1;
index = index + 1;
} else {
print("Retry: " + parsed::error::code + ". Use ASCII digits, for example 5, or q.\n");
}
}
summary("Completed", correct, answered, total);
return 0;
}
Follow the Linux instructions to run this example. Download the source to keep a copy.
Download main.asplExpected outcomes
{
"native": {
"check": 1,
"status": 1,
"output": "",
"reason": "private-member"
}
}From the failed English pair's directory run aspl check main.aspl or aspl run main.aspl; for its Arabic pair use الرئيسية.لبات. The import namespace exists, but answers::is_correct cannot name a private member. Changing the reading locale cannot fix accessibility.
Export and retry
Add share before fn is_correct in the failed answers.aspl, or شارك before دالة is_correct in its Arabic helper. Keep the root's answers::is_correct reference and both numeric arguments. Check the root again, then run and enter 5, 5, 12, 4, 15. Expect the same five-correct completion and status 0 as the exported pair.
Repair the private helper's export without changing the root's module-qualified call. Explain when the helper actually runs.
Hint: The module alias does not make declarations public. Add share / شارك to the helper declaration, keep answers::is_correct, then check the root.
Show worked answer
The corrected helper exports is_correct with two i64 parameters and a bool result. The root passes the record's expected answer and the parsed number through answers::is_correct. Import checks and makes the declaration available; it performs no call or input read. The explicit call in the successful parsing branch executes the helper. The full exported pair below checks successfully and retains the quiz's output and status.
Execution: Native only · ASPL 0.7.0
- Native only. Select ASPL 0.7.0. Download the root and its matching answers.aspl into one directory. Keep each vocabulary and the private/exported examples in separate directories. No data files are required.
Input lines: ["5","5","12","4","15"]
Arabic source · Required source modules, keep each variant in a separate directory:
English source · Required source modules, keep each variant in a separate directory:
import answers.aspl as answers;
record Question { prompt: string, answer: i64 }
fn summary(label: string, correct: i64, answered: i64, total: i64) -> unit {
print(label + ". Correct: " + format_i64(correct) + "; answered: " + format_i64(answered) + "; total: " + format_i64(total) + ".\n");
}
fn start_main() -> i64 {
let questions: list<Question> = [
Question { prompt: "2 + 3?", answer: 5 },
Question { prompt: "9 - 4?", answer: 5 },
Question { prompt: "3 * 4?", answer: 12 },
Question { prompt: "12 / 3?", answer: 4 },
Question { prompt: "7 + 8?", answer: 15 }
];
let total: i64 = length(questions);
var index: i64 = 0;
var answered: i64 = 0;
var correct: i64 = 0;
print("Quiz: " + format_i64(total) + " questions. Type q to stop.\n");
while (index < total) {
let question: Question = questions[index];
print("Question " + format_i64(index + 1) + "/" + format_i64(total) + ": " + question::prompt + " ");
let line: string = read_line();
if (line matches "q") {
summary("Stopped early", correct, answered, total);
return 0;
}
let parsed: result<i64> = parse_i64(line);
if (parsed::ok) {
if (answers::is_correct(question::answer, parsed::value)) {
print("Correct.\n");
correct = correct + 1;
} else {
print("Wrong. Expected " + format_i64(question::answer) + ".\n");
}
answered = answered + 1;
index = index + 1;
} else {
print("Retry: " + parsed::error::code + ". Use ASCII digits, for example 5, or q.\n");
}
}
summary("Completed", correct, answered, total);
return 0;
}
Follow the Linux instructions to run this example. Download the source to keep a copy.
Download main.asplExpected outcomes
{
"native": {
"check": 0,
"status": 0,
"output": "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 5; answered: 5; total: 5.\n"
}
}Check your understanding
Explain why the record stays private in the root, why the helper uses two numbers, why a module alias alone cannot expose a private declaration, and why importing executes no quiz. No score or progress is stored and navigation stays open. Return to next steps or the one-file browser version.