Skip to content

Commit 41826a3

Browse files
authored
doc: book section on lending row iterators (#406)
1 parent 5ccfc4f commit 41826a3

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

book/src/table_collection_row_access.md

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,53 @@
11
## Accessing table rows
22

3-
We may also access entire table rows by a row id:
3+
The rows of a table contain two types of data:
4+
5+
* Numerical data consisting of a single value.
6+
* Ragged data. Examples include metadata for all tables,
7+
ancestral states for sites, derived states for mutations,
8+
parent and location information for individuals, etc..
9+
10+
`tskit` provides two ways to access row data.
11+
The first is by a "view", which contains non-owning references
12+
to the ragged column data.
13+
The second is by row objects containing *copies* of the ragged column data.
14+
15+
The former will be more efficient when the ragged columns are populated.
16+
The latter will be more convenient to work with because the API is a standard
17+
rust iterator.
18+
19+
By holding references, row views have the usual implications for borrowing.
20+
The row objects, however, own their data and are thus independent of their parent
21+
objects.
22+
23+
### Row views
24+
25+
To generate a row view using a row id:
26+
27+
```rust, noplaygound, ignore
28+
{{#include ../../tests/book_table_collection.rs:get_edge_table_row_by_id}}
29+
```
30+
31+
To iterate over all views we use *lending* iterators:
32+
33+
```rust, noplaygound, ignore
34+
{{#include ../../tests/book_table_collection.rs:get_edge_table_rows_by_lending_iterator}}
35+
```
36+
37+
#### Lending iterators
38+
39+
The lending iterators are implemented using the [`streaming_iterator`](https://docs.rs/streaming-iterator/latest/streaming_iterator/) crate.
40+
(The community now prefers the term "lending" over "streaming" for this concept.)
41+
The `tskit` prelude includes the trait declarations that allow the code shown above to compile.
42+
43+
rust 1.65.0 stabilized Generic Associated Types, or GATs.
44+
GATs allows lending iterators to be implemented directly without the workarounds used in the `streaming_iterator` crate.
45+
We have decided not to implement our own lending iterator using GATs.
46+
Rather, we will see what the community settles on and will decide in the future whether or not to adopt it.
47+
48+
### Row objects
49+
50+
We may access entire table rows by a row id:
451

552
```rust, noplaygound, ignore
653
{{#include ../../tests/book_table_collection.rs:get_edge_table_row_by_id}}

tests/book_table_collection.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ fn add_node_handle_error() {
7070
#[test]
7171
fn get_data_from_edge_table() {
7272
use rand::distributions::Distribution;
73+
use tskit::prelude::*;
7374
let sequence_length = tskit::Position::from(100.0);
7475
let mut rng = rand::thread_rng();
7576
let random_pos = rand::distributions::Uniform::new::<f64, f64>(0., sequence_length.into());
@@ -120,6 +121,35 @@ fn get_data_from_edge_table() {
120121
}
121122
// ANCHOR_END: get_edge_table_row_by_id
122123

124+
// ANCHOR: get_edge_table_row_view_by_id
125+
if let Some(row_view) = tables.edges().row_view(edge_id) {
126+
assert_eq!(row_view.id, 0);
127+
assert_eq!(row_view.left, left);
128+
assert_eq!(row_view.right, right);
129+
assert_eq!(row_view.parent, parent);
130+
assert_eq!(row_view.child, child);
131+
} else {
132+
panic!("that should have worked...");
133+
}
134+
// ANCHOR_END: get_edge_table_row_view_by_id
135+
136+
// ANCHOR: get_edge_table_rows_by_lending_iterator
137+
let mut edge_table_lending_iter = tables.edges().lending_iter();
138+
while let Some(row_view) = edge_table_lending_iter.next() {
139+
// there is only one row!
140+
assert_eq!(row_view.id, 0);
141+
assert_eq!(row_view.left, left);
142+
assert_eq!(row_view.right, right);
143+
assert_eq!(row_view.parent, parent);
144+
assert_eq!(row_view.child, child);
145+
assert!(row_view.metadata.is_none()); // no metadata in our table
146+
}
147+
// ANCHOR_END: get_edge_table_rows_by_lending_iterator
148+
149+
assert!(tables
150+
.check_integrity(tskit::TableIntegrityCheckFlags::default())
151+
.is_ok());
152+
123153
// ANCHOR: get_edge_table_rows_by_iterator
124154
for row in tables.edges_iter() {
125155
// there is only one row!

0 commit comments

Comments
 (0)