Paths for Referring to an Item in the Module Tree
To show Cairo where to find an item in a module tree, we use a path in the same way we use a path when navigating a filesystem. To call a function, we need to know its path.
A path can take two forms:
-
An absolute path is the full path starting from a crate root. The absolute path begins with the crate name.
-
A relative path starts from the current module.
Both absolute and relative paths are followed by one or more identifiers separated by double colons (
::
).
To illustrate this notion let's take back our example Listing 7-1 for the restaurant we used in the last chapter. We have a crate named restaurant
in which we have a module named front_of_house
that contains a module named hosting
. The hosting
module contains a function named add_to_waitlist
. We want to call the add_to_waitlist
function from the eat_at_restaurant
function. We need to tell Cairo the path to the add_to_waitlist
function so it can find it.
Filename: src/lib.cairo
mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
fn seat_at_table() {}
}
mod serving {
fn take_order() {}
fn serve_order() {}
fn take_payment() {}
}
}
fn eat_at_restaurant() {
// Absolute path
restaurant::front_of_house::hosting::add_to_waitlist(); // ✅ Compiles
// Relative path
front_of_house::hosting::add_to_waitlist(); // ✅ Compiles
}
The first time we call the add_to_waitlist
function in eat_at_restaurant
,
we use an absolute path. The add_to_waitlist
function is defined in the same
crate as eat_at_restaurant
. In Cairo, absolute paths start from the crate root, which you need to refer to by using the crate name.
The second time we call add_to_waitlist
, we use a relative path. The path starts with front_of_house
, the name of the module
defined at the same level of the module tree as eat_at_restaurant
. Here the
filesystem equivalent would be using the path
./front_of_house/hosting/add_to_waitlist
. Starting with a module name means
that the path is relative to the current module.
Starting Relative Paths with super
Choosing whether to use a super
or not is a decision you’ll make
based on your project, and depends on whether you’re more likely to move item
definition code separately from or together with the code that uses the item.
Filename: src/lib.cairo
fn deliver_order() {}
mod back_of_house {
fn fix_incorrect_order() {
cook_order();
super::deliver_order();
}
fn cook_order() {}
}
Here you can see directly that you access a parent's module easily using super
, which wasn't the case previously.