RFC: Reference Iterator for better in place loop modifications

#1

Has there ever been any discussion of creating a RefsIterator type and the accompanying refs(collection) which returns a Ref to the values of a collection?

So you could write:

col=collect(1:1000)
for r in refs(col)
    r[]=... r[]...
    ....
end

You could of course do refs(values(dict)) as well but you would want to limit this collections where modification to the values is valid. So no refs(keys(::Dict)) but maybe refs(keys(::OrderedDict)) ?

This seems like the easiest way to enable more generic in place modification via loops.

#2

Seems like a nice idea. If somebody wrote a package for this, I’d probably use it.

#3

I would advocate for it to be part of Base so that it becomes consistent across the ecosystem.

#4
1 Like
#5

The time frame in #12157 is a little beyond my julia horizon, so some of the implementation seems a bit heavy.

But I was thinking something as simple as

struct RefsIterator{T}
    dict::T
end

then for dict it would like like

@propagate_inbounds function Base.iterate(v::T, i::Union{Int,Nothing}=v.dict.idxfloor) where T <:RefsIterator{ValueIterator{<:Dict}}
    i === nothing && return nothing # This is to catch nothing returned when i = typemax
    i = skip_deleted(v.dict, i)
    i === nothing && return nothing # This is to catch nothing returned by skip_deleted
    vals = T <: KeySet ? v.dict.keys : v.dict.vals
    (@inbounds Ref(vals,i), i == typemax(Int) ? nothing : i+1)
end

There likely could be some improvement made so that a new ref isn’t created every iteration but it should be that simple.