Struct arithmetic_typing::Tuple
source · pub struct Tuple<Prim: PrimitiveType = Num> { /* private fields */ }
Expand description
Tuple type.
Most generally, a tuple type consists of three fragments: start,
middle and end. Types at the start and at the end are heterogeneous,
while the middle always contains items of the same type (but the number
of these items can generally vary). A Slice
is a partial case of a tuple type;
i.e., a type with the empty start and end. Likewise, a Rust-like tuple is a tuple
that only has a start.
§Notation
A tuple type is denoted like (T, U, ...[V; _], X, Y)
, where T
and U
are types
at the start, V
is the middle type, and X
, Y
are types at the end.
The number of middle elements can be parametric, such as N
.
If a tuple only has a start, this notation collapses into Rust-like (T, U)
.
If a tuple only has a middle part (Self::as_slice()
returns Some(_)
),
it is denoted as the corresponding slice, something like [T; N]
.
§Indexing
Indexing is accessing tuple elements via an expression like xs.0
.
Tuple indexing is supported via FieldAccess
expr,
where the field name is a decimal usize
number.
The indexing support for type inference is quite limited.
For it to work, the receiver type must be known to be a tuple, and the index must be such
that the type of the corresponding element is decidable. Otherwise,
an UnsupportedIndex
error will be raised.
Tuple type | Index | Outcome |
---|---|---|
(Num, Bool) | 0 | Num |
(Num, Bool) | 1 | Bool |
(Num, Bool) | 2 | Hard error; the index is out of bounds. |
Num | 0 | Hard error; only tuples can be indexed. |
[Num; _] | 0 | Error; the slice may be empty. |
[Num; _ + 1] | 0 | Num ; the slice is guaranteed to have 0th element. |
(Bool, ...[Num; _]) | 0 | Bool |
(Bool, ...[Num; _]) | 1 | Error; the slice part may be empty. |
(...[Num; _], Bool) | 0 | Error; cannot decide if the result is Num or Bool . |
§Examples
Simple tuples can be created using the From
trait. Complex tuples can be created
via Self::new()
.
let simple_tuple = Tuple::from(vec![Type::NUM, Type::BOOL]);
assert_matches!(simple_tuple.parts(), ([_, _], None, []));
assert!(simple_tuple.as_slice().is_none());
assert_eq!(simple_tuple.to_string(), "(Num, Bool)");
let slice_tuple = Tuple::from(
Type::NUM.repeat(UnknownLen::param(0)),
);
assert_matches!(slice_tuple.parts(), ([], Some(_), []));
assert!(slice_tuple.as_slice().is_some());
assert_eq!(slice_tuple.to_string(), "[Num; N]");
let complex_tuple = Tuple::new(
vec![Type::NUM],
Type::NUM.repeat(UnknownLen::param(0)),
vec![Type::BOOL, Type::param(0)],
);
assert_matches!(complex_tuple.parts(), ([_], Some(_), [_, _]));
assert_eq!(complex_tuple.to_string(), "(Num, ...[Num; N], Bool, 'T)");
Implementations§
source§impl<Prim: PrimitiveType> Tuple<Prim>
impl<Prim: PrimitiveType> Tuple<Prim>
sourcepub fn new(
start: Vec<Type<Prim>>,
middle: Slice<Prim>,
end: Vec<Type<Prim>>,
) -> Self
pub fn new( start: Vec<Type<Prim>>, middle: Slice<Prim>, end: Vec<Type<Prim>>, ) -> Self
Creates a new complex tuple.
sourcepub fn as_slice(&self) -> Option<&Slice<Prim>>
pub fn as_slice(&self) -> Option<&Slice<Prim>>
Returns this tuple as slice if it fits (has no start or end components).
sourcepub fn parts(&self) -> (&[Type<Prim>], Option<&Slice<Prim>>, &[Type<Prim>])
pub fn parts(&self) -> (&[Type<Prim>], Option<&Slice<Prim>>, &[Type<Prim>])
Returns shared references to the parts comprising this tuple: start, middle, and end.
sourcepub fn parts_mut(
&mut self,
) -> (&mut [Type<Prim>], Option<&mut Slice<Prim>>, &mut [Type<Prim>])
pub fn parts_mut( &mut self, ) -> (&mut [Type<Prim>], Option<&mut Slice<Prim>>, &mut [Type<Prim>])
Returns exclusive references to the parts comprising this tuple: start, middle, and end.
sourcepub fn len(&self) -> TupleLen
pub fn len(&self) -> TupleLen
Returns the length of this tuple.
§Examples
let tuple = Tuple::from(vec![Type::NUM, Type::BOOL]);
assert_eq!(tuple.len(), TupleLen::from(2));
let slice = Slice::new(Type::NUM, UnknownLen::param(0));
let tuple = Tuple::from(slice.clone());
assert_eq!(tuple.len(), TupleLen::from(UnknownLen::param(0)));
let tuple = Tuple::new(vec![], slice, vec![Type::BOOL]);
assert_eq!(tuple.len(), UnknownLen::param(0) + 1);
sourcepub fn element_types(
&self,
) -> impl Iterator<Item = (TupleIndex, &Type<Prim>)> + '_
pub fn element_types( &self, ) -> impl Iterator<Item = (TupleIndex, &Type<Prim>)> + '_
Iterates over all distinct elements in this tuple. The iteration is performed in order.
§Examples
let complex_tuple = Tuple::new(
vec![Type::NUM],
Slice::new(Type::NUM, UnknownLen::param(0)),
vec![Type::BOOL, Type::param(0)],
);
let elements: Vec<_> = complex_tuple.element_types().collect();
assert_eq!(elements, [
(TupleIndex::Start(0), &Type::NUM),
(TupleIndex::Middle, &Type::NUM),
(TupleIndex::End(0), &Type::BOOL),
(TupleIndex::End(1), &Type::param(0)),
]);
Trait Implementations§
source§impl<Prim: PrimitiveType> Display for Tuple<Prim>
impl<Prim: PrimitiveType> Display for Tuple<Prim>
Auto Trait Implementations§
impl<Prim> Freeze for Tuple<Prim>
impl<Prim = Num> !RefUnwindSafe for Tuple<Prim>
impl<Prim> Send for Tuple<Prim>
impl<Prim> Sync for Tuple<Prim>
impl<Prim> Unpin for Tuple<Prim>where
Prim: Unpin,
impl<Prim = Num> !UnwindSafe for Tuple<Prim>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
default unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)