Main API:
FieldViews.FieldViewable — TypeFieldViewable(array::AbstractArray{T,N}) :: FieldViewable{T,N,Store}Wrap an array to enable zero-copy field access via properties.
FieldViewable provides a view-like interface for accessing individual fields of immutable structs stored in an array, without copying data. Field access returns FieldView objects that can be indexed and modified in-place, with changes reflected in the original array.
Requirements:
- Element type
Tmust be a concrete, immutable struct (but can have non-concrete, or mutable elements!)
Examples
struct Point{T}
x::T
y::T
z::T
end
points = [Point(1.0, 2.0, 3.0), Point(4.0, 5.0, 6.0)]
fv = FieldViewable(points)
# Access field views
fv.x # Returns FieldView{:x, Float64, ...}
fv.x[1] # Returns 1.0
# Modify in-place (modifies original array)
fv.x[1] = 10.0
points[1].x # Now 10.0
# Take views
slice = view(fv, 1:1)
slice.y[1] = 99.0
points[1].y # Now 99.0See also
FieldViews.FieldView — TypeFieldView{field}(parent::AbstractArray)A view of a specific field across all elements in an array.
FieldView provides element-wise access to a single field of the structs in the parent array. For isbits fields and strided array containers, it uses efficient pointer methods for direct field access. For non-isbits fields, or non-strided arrays it uses a slower fallback which loads the full struct and extracts the field value.
Users typically obtain FieldView objects through property access on FieldViewable:
fv = FieldViewable(points)
x_view = fv.x # Returns a FieldView{:x, ...}Indexing
FieldView supports standard array indexing operations:
fv.x[i]- Get field value at index ifv.x[i] = val- Set field value at index i (modifies parent array)
Examples
struct Data{T}
value::T
weight::Float64
end
arr = [Data(1, 0.5), Data(2, 1.5)]
fv = FieldViewable(arr)
# Access field view
values = fv.value # FieldView{:value, Int64, ...}
values[1] # 1
# Modify through view
fv.weight[2] = 2.0
arr[2].weight # 2.0Adaptions for custom types:
FieldViews.fieldmap — Functionfieldmap(::Type{T}) :: TupleDefine the field layout for type T to be used by FieldViews.
Add methods to this function to customize how FieldViews accesses fields in your types. This is essential for:
- Flattening nested structures
- Renaming fields
- Exposing only certain fields
Default Behavior
By default, returns fieldnames(T), exposing all fields with their original names.
Return Value
A tuple where each element is one of:
SymbolorInt: Direct field accessPair{Symbol,Symbol}: Nested field (e.g.,:outer => :inner)Pair{Symbol,Renamed}: Nested field with renameRenamed: Renamed direct field
Examples
Flattening nested structures
struct MyType{T}
x::T
rest::@NamedTuple{a::Int, b::Int}
end
function FieldViews.fieldmap(::Type{MyType{T}}) where T
(:x, :rest => :a, :rest => :b)
end
fv = FieldViewable([MyType(1.0, (a=1, b=2))])
fv.a[1] # Access nested field directly, returns 1Renaming fields
struct Foo
data::@NamedTuple{_internal::Int}
end
function FieldViews.fieldmap(::Type{Foo})
(:data => Renamed(:_internal, :public),)
end
fv = FieldViewable([Foo((_internal=42,))])
fv.public[1] # Returns 42See also
Renamed: For field aliasingmappedfieldschema: The processed schema generated fromfieldmap
FieldViews.Renamed — TypeRenamed(actual::Union{Int,Symbol}, alias::Symbol)Specify a field rename in custom field mappings.
Used within fieldmap definitions to expose an internal field under a different name. This is useful when you want to expose a given field using a different name, or access Tuple fields (since their fields are just integers).
Arguments
actual: The real field name or field index in the structalias: The name to expose in theFieldViewableinterface
Examples
struct Foo
data::@NamedTuple{_x::Int, _y::Int}
end
function FieldViews.fieldmap(::Type{Foo})
(:data => Renamed(:_x, :x), :data => Renamed(:_y, :y))
end
fv = FieldViewable([Foo((_x=1, _y=2))])
fv.x[1] # Access via alias 'x', returns 1See also
fieldmap: Define custom field layouts usingRenamed
FieldViews.StridedArrayTrait — TypeStridedArrayTrait(::Type{T}) :: StridedArrayTrait
StridedArrayTrait(x) :: StridedArrayTraitQuery or define whether an array type has strided memory layout.
Returns IsStrided() if the array has constant stride offsets in memory, or Unknown() otherwise. Arrays which support IsStrided() auotmatically get more efficient getindex/setindex! implementations for their isbits fields.
IsStrided arrays must support pointer(v, i) methods, and linear indexing.
Default Behavior
StridedArraytypes returnIsStrided()- Other
AbstractArraytypes returnUnknown()
Extending Support
To opt into the strided interface for a custom array type:
FieldViews.StridedArrayTrait(::Type{<:MyArrayType}) = FieldViews.IsStrided()Examples
StridedArrayTrait(Vector{Int}) # IsStrided()
StridedArrayTrait(view([1,2,3,4], 1:2:4)) # IsStrided()
StridedArrayTrait(view([1,2,3,4], [1,3,4])) # Unknown() - non-contiguous indicesA strided array is one where elements are stored at fixed offsets from each other in memory. For example, [1, 2, 3, 4] is strided, as is view(v, 1:2:4) (every other element), but view(v, [1, 3, 4]) is not strided (arbitrary indices).
See also
FieldViews.IsStrided — TypeIsStrided <: StridedArrayTraitTrait indicating that an array type has strided (constant offset) memory layout.
Used by FieldViews to dispatch on array types that support efficient field access through pointer arithmetic.
See also
StridedArrayTrait: The trait function for querying array layoutUnknown: Trait for non-strided arrays
FieldViews.Unknown — TypeUnknown <: StridedArrayTraitTrait indicating that an array type's memory layout is unknown or non-strided.
For arrays with this trait, FieldViews will fall back on accessing/modifying field elements by loading/storing the entire containing struct, and then using FieldLens to manipulate and set the required field. This can be slower in some circumstances.
See also
StridedArrayTrait: The trait function for querying array layoutIsStrided: Trait for strided arrays
Utility
FieldViews.FieldLens — TypeFieldLens{field}An optic for accessing and modifying a specific field of a struct.
FieldLens implements the lens interface from Accessors.jl, providing functional field access and immutable updates. It is primarily used internally by FieldViews for non-isbits field access, but can also be used directly with the Accessors.jl API.
Constructor
FieldLens(field::Union{Symbol,Int})
FieldLens{field}()Examples
struct Point{T}
x::T
y::T
end
lens = FieldLens{:x}()
p = Point(1, 2)
lens(p) # Get: returns 1
using Accessors
set(p, lens, 10) # Set: returns Point(10, 2)See also
- Accessors.jl documentation for general lens usage
Dangerous tools
FieldViews.mappedfieldschema — Functionmappedfieldschema(::Type{T}) -> NamedTupleCompute the complete field schema for type T, computed using its fieldmap.
Returns a NamedTuple mapping field names (after renaming) to schema information containing:
lens: An optic for accessing the fieldoffset: Byte offset of the field in memory (forisbitsfields)type: The field's data type
This function processes the output of fieldmap to generate the internal schema used by FieldViews for efficient field access.
Examples
struct Point{T}
x::T
y::T
z::T
end
schema = FieldViews.mappedfieldschema(Point{Float64})
# Returns: (x = (lens=..., offset=0, type=Float64),
# y = (lens=..., offset=8, type=Float64),
# z = (lens=..., offset=16, type=Float64))
schema.x.offset # 0
schema.y.offset # 8
schema.z.type # Float64Implementation Note
This is typically called internally by FieldViews and rarely needs to be called directly by users. Adding methods to mappedfieldschema incorrectly could cause undefined behaviour.
See also
fieldmap: The user-facing API for defining field layouts