Packages#
Packages in Jac are directories containing .jac or .py files.
Prefer Absolute Imports
Use absolute imports like import from mypackage.module { X } for clarity and maintainability.
Simple Package (No __init__.jac Required)#
Import directly from a package directory. The __init__.jac file is optional.
package_no_init/
├── main.jac
└── mylib/ # No __init__.jac needed!
├── math_utils.jac
└── string_utils.jac
Output
```
add(3, 5): 8 multiply(4, 6): 24 greet('World'): Hello, World! ```
Package with Re-exports#
Use __init__.jac when you want to create a simplified public API.
package_basic/
├── main.jac
└── mypackage/
├── __init__.jac # Re-exports from helper.jac
└── helper.jac
Output
```
Package from-import - HELPER_VALUE: Helper value from package Package from-import - helper_func(): Helper function result ```
Nested Package Imports#
Access deeply nested packages using dot notation.
nested_packages/
├── main.jac
└── app/
├── __init__.jac
├── constants.jac
├── models/
│ ├── __init__.jac
│ └── user.jac
└── services/
├── __init__.jac
└── user_service.jac
Output
```
Nested deep - APP_NAME: MyApp Nested deep - get_version(): 1.0.0 Nested deep - create_user('Alice'): User(Alice) from MyApp ```
Re-exports with __init__.jac#
While optional, __init__.jac can be used to create a clean public API by re-exporting symbols.
init_reexport/
├── main.jac
└── mathlib/
├── __init__.jac # Re-exports from submodules
├── calculator.jac
├── constants.jac
└── operations.jac
Output
```
Init reexport - add(5, 3): 8 Init reexport - subtract(10, 4): 6 Init reexport - multiply(6, 7): 42 Init reexport - divide(20, 4): 5.0 Init reexport - PI: 3.14159 Init reexport - E: 2.71828 Init reexport - Calculator.compute(10, 2, 'add'): 12 ```
When to use __init__.jac
Use __init__.jac when you want to:
- Create a simplified public API
- Hide internal module structure
- Add package-level constants or initialization
Sibling Subpackage Imports#
Import between sibling subpackages using absolute paths.
sibling_subpackage/
├── main.jac
└── top/
├── __init__.jac
├── sub_a/
│ ├── __init__.jac
│ └── a_module.jac
└── sub_b/
├── __init__.jac
└── b_module.jac # Can import from sub_a
Output
```
Sibling subpkg - A_VALUE: A module value Sibling subpkg - a_func(): A function Sibling subpkg - B_VALUE: B uses A module value Sibling subpkg - b_func(): B calls: A function ```
Key Takeaways#
| Concept | Description |
|---|---|
| Packages | Directories with .jac or .py files |
__init__.jac |
Optional, useful for re-exports |
| Absolute imports | import from pkg.subpkg.module { X } |
| Nested access | Use dot notation for deep packages |
Best Practice
Use absolute imports with full package paths: import from app.models.user { User }. This is explicit and avoids ambiguity.