Part VI: Concurrency
Part VI: Concurrency
Section titled “Part VI: Concurrency”In this part:
- Async/Await - Async functions, async walkers, async for
- Concurrent Expressions - flow/wait for parallel tasks
Jac supports Python-style async/await for concurrent I/O operations, plus a unique flow/wait syntax for launching and collecting parallel tasks. Use async when you need non-blocking I/O (like HTTP requests), and flow when you want to run multiple independent operations concurrently.
Async/Await
Section titled “Async/Await”The async/await syntax works like Python’s — async marks a function as a coroutine, and await suspends execution until the awaited operation completes. Walkers can also be async, enabling non-blocking graph traversal with I/O at each node.
1 Async Functions
Section titled “1 Async Functions”async def fetch_data(url: str) -> dict { response = await http_get(url); return await response.json();}
async def process_multiple(urls: list[str]) -> list[dict] { results = []; for url in urls { data = await fetch_data(url); results.append(data); } return results;}2 Async Walkers
Section titled “2 Async Walkers”async walker DataFetcher { has url: str;
async can fetch with Root entry { data = await http_get(self.url); report data; }}Use async walker for non-blocking I/O during traversal.
3 Async For Loops
Section titled “3 Async For Loops”async def process_stream(stream: AsyncIterator) -> None { async for item in stream { print(item); }}Concurrent Expressions
Section titled “Concurrent Expressions”The flow/wait pattern provides explicit concurrency control. flow launches a task and immediately returns a future (without blocking), while wait retrieves the result (blocking if necessary). This is more explicit than async/await — you decide exactly when to start parallel work and when to synchronize.
1 flow Keyword
Section titled “1 flow Keyword”The flow keyword launches a function call as a background task and returns a future immediately. Use it when you have independent operations that can run in parallel.
def expensive_computation -> int { return 42;}
def do_something_else -> int { return 1;}
with entry { future = flow expensive_computation();
# Do other work while computation runs other_result = do_something_else();
# Wait for result when needed result = wait future;}2 Parallel Operations
Section titled “2 Parallel Operations”def fetch_users -> list { return [];}
def fetch_orders -> list { return [];}
def fetch_inventory -> list { return [];}
def process_local_data { # Process local data here}
with entry { # Launch multiple operations in parallel future1 = flow fetch_users(); future2 = flow fetch_orders(); future3 = flow fetch_inventory();
# Continue with other work process_local_data();
# Collect all results users = wait future1; orders = wait future2; inventory = wait future3;}3 flow vs async
Section titled “3 flow vs async”| Feature | async/await | flow/wait |
|---|---|---|
| Model | Event loop (cooperative) | Thread pool (parallel) |
| Best for | I/O-bound, many concurrent | CPU-bound, few concurrent |
| Blocking | Non-blocking | Can block threads |
Learn More
Section titled “Learn More”Related Reference:
- Part I: Foundation - Control flow basics
- Part V: AI Integration - Async LLM calls