Julia – 51 – interfacce – 2

Continuo da qui, copio qui.

Arrays astratti

Methods to implement               Brief description
size(A)                            Returns a tuple containing the dimensions of A
getindex(A, i::Int)                (if IndexLinear) Linear scalar indexing
getindex(A, I::Vararg{Int, N})     (if IndexCartesian, where N = ndims(A)) 
                                   N-dimensional scalar indexing
setindex!(A, v, i::Int)            (if IndexLinear) Scalar indexed assignment
setindex!(A, v, I::Vararg{Int, N}) (if IndexCartesian, where N = ndims(A)) 
                                   N-dimensional scalar indexed assignment
Optional methods              Default definition     Brief description
IndexStyle(::Type)            IndexCartesian()       Returns either IndexLinear() 
                                                     or IndexCartesian(). 
                                                     See the description below.
getindex(A, I...)             defined in terms       Multidimensional and 
                              of scalar getindex()   nonscalar indexing
setindex!(A, I...)            defined in terms of    Multidimensional and 
                              scalar setindex!()     nonscalar indexed assignment
start()/next()/done()         defined in terms of    Iteration
                              scalar getindex()
length(A)                     prod(size(A))          Number of elements
similar(A)                    similar(A, eltype(A),  Return a mutable array with
                              size(A))               the same shape and
                                                     element type
similar(A, ::Type{S})         similar(A, S, size(A)) Return a mutable array 
                                                     with the same shape and 
                                                     the specified element type
similar(A, dims::NTuple{Int}) similar(A, eltype(A),  Return a mutable array with 
                              dims)                  the same element type and
                                                     size dims
similar(A, ::Type{S},         Array{S}(dims)         Return a mutable array 
dims::NTuple{Int})                                   with the specified element
                                                     type and size
Non-traditional indices    Default definition        Brief description
indices(A)                 map(OneTo, size(A))       Return the
                                                     AbstractUnitRange of 
                                                     valid indices
Base.similar(A, ::Type{S}, similar(A, S,             Return a mutable array 
inds::NTuple{Ind})         Base.to_shape(inds))      with the specified indices
                                                     inds (see below)
Base.similar(T::Union{     T(Base.to_shape(inds))    Return an array similar to 
    Type,Function}, inds)                            T with the specified
                                                     indices inds (see below)

If a type is defined as a subtype of AbstractArray, it inherits a very large set of rich behaviors including iteration and multidimensional indexing built on top of single-element access. See the arrays manual page [prossimamente] and standard library section [prossimamente] for more supported methods.

A key part in defining an AbstractArray subtype is IndexStyle. Since indexing is such an important part of an array and often occurs in hot loops, it’s important to make both indexing and indexed assignment as efficient as possible. Array data structures are typically defined in one of two ways: either it most efficiently accesses its elements using just one index (linear indexing) or it intrinsically accesses the elements with indices specified for every dimension. These two modalities are identified by Julia as IndexLinear() and IndexCartesian(). Converting a linear index to multiple indexing subscripts is typically very expensive, so this provides a traits-based mechanism to enable efficient generic code for all array types.

This distinction determines which scalar indexing methods the type must define. IndexLinear() arrays are simple: just define getindex(A::ArrayType, i::Int). When the array is subsequently indexed with a multidimensional set of indices, the fallback getindex(A::AbstractArray, I...)() efficiently converts the indices into one linear index and then calls the above method. IndexCartesian() arrays, on the other hand, require methods to be defined for each supported dimensionality with ndims(A)Int indices. For example, the builtin SparseMatrixCSC type only supports two dimensions, so it just defines getindex(A::SparseMatrixCSC, i::Int, j::Int)(). The same holds for setindex!().

Returning to the sequence of squares from above [post precedente], we could instead define it as a subtype of an AbstractArray{Int, 1}:

Note that it’s very important to specify the two parameters of the AbstractArray; the first defines the eltype(), and the second defines the ndims(). That supertype and those three methods are all it takes for SquaresVector to be an iterable, indexable, and completely functional array:

As a more complicated example, let’s define our own toy N-dimensional sparse-like array type built on top of Dict:

Notice that this is an IndexCartesian array, so we must manually define getindex() and setindex!() at the dimensionality of the array. Unlike the SquaresVector, we are able to define setindex!(), and so we can mutate the array:

The result of indexing an AbstractArray can itself be an array (for instance when indexing by a Range). The AbstractArray fallback methods use similar() to allocate an Array of the appropriate size and element type, which is filled in using the basic indexing method described above. However, when implementing an array wrapper you often want the result to be wrapped as well:

In this example it is accomplished by defining Base.similar{T}(A::SparseArray, ::Type{T}, dims::Dims) to create the appropriate wrapped array. (Note that while similar supports 1- and 2-argument forms, in most case you only need to specialize the 3-argument form.) For this to work it’s important that SparseArray is mutable (supports setindex!). Defining similar(), getindex() and setindex!() for SparseArray also makes it possible to copy() the array:

In addition to all the iterable and indexable methods from above, these types can also interact with each other and use most of the methods defined in the standard library for AbstractArrays:

If you are defining an array type that allows non-traditional indexing (indices that start at something other than 1), you should specialize indices. You should also specialize similar so that the dims argument (ordinarily a Dims size-tuple) can accept AbstractUnitRange objects, perhaps range-types Ind of your own design. For more information, see Arrays with custom indices.


Posta un commento o usa questo indirizzo per il trackback.



Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: