Guided project: carry one workflow through the fundamentals¶
The Incan Book teaches language concepts in small programs. This guided spine gives those concepts one cumulative destination: the release-envelope executable pipeline mini-project.
- ShapeTyped transformation
- FailExplicit Result
- OrganizeProject boundary
- TestBoth outcomes
- DeliverLock and build
Stage 1: shape one transformation¶
Read values, variables, and types, functions, and control flow. Begin with one pure, typed operation:
def normalize_name(name: str) -> str: # (1)
return name.strip().lower()
- The signature makes the step's input and output visible before any execution or orchestration is introduced.
This is deliberately small. The project becomes useful by strengthening its boundary, not by adding framework machinery.
Stage 2: make rejection explicit¶
Read errors with Result, Option, and ?. A blank name is not a successful normalized value, so move that fact into the return type:
pub def normalize_name(name: str) -> Result[str, str]: # (1)
if len(name.strip()) == 0:
return Err("name must not be empty") # (2)
return Ok(name.strip().lower())
Result[str, str]requires callers to acknowledge both the useful value and the failure.- The failure travels as data; the step does not print, exit, or mutate ambient state.
At the terminal boundary, one match is clearer than a combinator chain because both branches intentionally produce visible output:
def main() -> None:
match normalize_name(" Alice "):
case Ok(value): println(f"ok: {value}")
case Err(error): println(f"err: {error}")
Stage 3: organize the project¶
Read modules and imports, then follow the mini-project's manifest-backed layout. Keep the public step and terminal main in src/pipeline_step.incn; point [project.scripts] main at that file.
The manifest owns the entry point. Tests import the public function as from pipeline_step import normalize_name; they do not climb directories or duplicate the function.
Stage 4: test both contracts¶
Read unit tests, then add the mini-project's success and failure tests.
Run the complete test gate:
incan test
A useful workflow test proves both the ordinary value and the rejected input. It does not merely assert that the program starts.
Stage 5: deliver the program¶
Lock, run, and release-build the completed project:
incan lock
incan run --locked
incan test --locked
incan build --locked
The same source, manifest, and lock authority now drive local execution, tests, and the native artifact.
You carried one workflow from a small typed function through explicit fallibility, a public module boundary, focused tests, a canonical lock, and a native build—all inside the 0.5 release envelope.
Next¶
- Build and consume an Incan library
- Diagnose a failed build
- Build a typed data processor when you want to carry the same explicit workflow shape into typed JSON and file boundaries