Named vectors
A named vector is similar to a named tuple, which associate each of its values with a name. Although the names of a named vector cannot be changed, the values can be modified if needed. In contrast to the predefined NamedTuple
in Julia, which employs the names as type parameters, we just implement a named vector as a composite struct equipped with the getindex
and setindex!
functions, with the fieldnames being its names. This simple implementation makes it possible to define your own concrete named vector with any of your preferred type names, and ensures that all instances of a certain concrete named vector share the same names. Therefore, if you are familiar with Python, you will find that our named vector is more qualified to be the counterpart of the namedtuple
in Python than the default Julia implementation. Last but not least important, it is also worth noted that a named vector is not a vector, as is similar to that a named tuple is not a tuple in Julia. This results from our basic expectation that a named vector should be more like a tuple other than a vector so that not all operations valid to vectors are also valid to named vectors.
NamedVector
NamedVector
defines the abstract type for all concrete named vectors.
Main features include:
- Values can be accessed or modified either by the
.
operator or by the[]
operator. - Comparisons, such as
≡
,≢
,==
,≠
,>
,<
,≥
,≤
are supported. Therefore a vector of named vectors can be sorted by the defaultsort
function. - Hash is supported by
hash
. Therefore, a named vector can be used as the key of a dict or set. - Iteration over its fieldnames is supported by
keys
, over its values is supported byvalues
, over its field-value pairs is supported bypairs
. - A reverse iteration is also supported.
To subtype it, please note:
- A concrete type can be either mutable or immutable as you need, which is different from tuples.
- The fields of a concrete type can be of the same type or not. For the former, we denote the named vector as "homogeneous" while for the latter as "inhomogeneous". For homogeneous ones, we define a sub abstract type,
HomoNamedVector
for further optimization of the default methods. See HomoNamedVector below. - For all concrete subtypes, if inner constructors are defined, the one which has the same interface with the default one must be implemented. Otherwise, some functionalities will not work.
- Arithmetic operations, such as
+
,-
,*
,/
,%
,÷
, etc. are not supported. However, the functionmap
is implemented, which can help users do the overloadings of these operations.
HomoNamedVector
HomoNamedVector
is the subtype of NamedVector
that of all its fields share the same type. Compared to NamedVector
, one more default method is implemented with HomoNamedVector
, i.e. eltype
, which returns the type of its fields. This function ensures the type stability of all the methods that involves an iteration of the field values of a named vector. Therefore, homogeneous named vector are usually more efficient than inhomogeneous ones. Use homogeneous ones as much as possible unless the code efficiency does not matter.
To subtype HomoNamedVector
, all the suggestions mentioned in the previous subsection for NamedVector
also applies. A recommended template for a subtype is
[mutable] struct YourNamedVector{T} <: HomoNamedVector{T}
filed1::T
filed2::T
...
end
Manual
QuantumLattices.Prerequisites.NamedVectors.HomoNamedVector
— TypeHomoNamedVector{T}
Abstract type for all homogeneous named vectors.
QuantumLattices.Prerequisites.NamedVectors.NamedVector
— TypeNamedVector
Abstract type for all named vectors.
Base.:<
— Method<(nv1::NamedVector, nv2::NamedVector) -> Bool
Compare two named vectors and judge whether the first is less than the second.
Base.:==
— Method==(nv1::NamedVector, nv2::NamedVector) -> Bool
Overloaded equivalent operator. Two named vector are equal to each other if and only if their keys as well as their values are equal to each other.
It is not necessary for two named vectors to be of the same concrete type to be equal to each other.
Base.convert
— Methodconvert(::Type{Tuple}, nv::NamedVector) -> Tuple
convert(::Type{NV}, nv::Tuple) where {NV<:NamedVector} -> NV
Convert a named vector to tuple and vice versa.
Base.eltype
— Methodeltype(::Type{<:HomoNamedVector{T}}) where T
eltype(nv::HomoNamedVector)
Get the type parameter of a concrete HomoNamedVector
.
Base.getindex
— Methodgetindex(nv::NamedVector, index::Int)
Get the value by the []
syntax.
Base.hash
— Methodhash(nv::NamedVector, h::UInt)
Hash a concrete NamedVector
.
Base.isequal
— Methodisequal(nv1::NamedVector, nv2::NamedVector) -> Bool
Overloaded equivalent operator. Two named vector are equal to each other if and only if their keys as well as their values are equal to each other.
It is not necessary for two named vectors to be of the same concrete type to be equal to each other.
Base.isless
— Methodisless(nv1::NamedVector, nv2::NamedVector) -> Bool
Compare two named vectors and judge whether the first is less than the second.
Base.iterate
— Functioniterate(nv::NamedVector, state=1)
iterate(rv::Iterators.Reverse{<:NamedVector}, state=length(rv.itr))
Iterate or reversely iterate over the values of a concrete NamedVector
.
Base.keys
— Methodkeys(nv::NamedVector) -> NTuple{length(nv), Symbol}
Iterate over the names.
Base.length
— Methodlength(::Type{NV}) where NV<:NamedVector -> Int
length(nv::NamedVector) -> Int
Get the length of a concrete NamedVector
.
Base.map
— Methodmap(f, nvs::NV...) where NV<:NamedVector -> NV
Apply function f
elementwise on the input named vectors.
Base.pairs
— Methodpairs(nv::NamedVector) -> Base.Generator
Iterate over the name-value pairs.
Base.replace
— Methodreplace(nv::NamedVector; kwargs...) -> typeof(nv)
Return a copy of a concrete NamedVector
with some of the field values replaced by the keyword arguments.
Base.setindex!
— Methodsetindex!(nv::NamedVector, value, index::Int)
Set the value by the []
syntax if mutable.
Base.show
— Methodshow(io::IO, nv::NamedVector)
Show a concrete NamedVector
.
Base.values
— Methodvalues(nv::NamedVector) -> NTuple{length(nv)}
Iterate over the values.
Base.zero
— Methodzero(::Type{NV}) where NV<:NamedVector -> NV
zero(nv::NamedVector) -> typeof(nv)
Get a concrete NamedVector
with all values being zero.