mkitti / Ranges.jl

Additional range syntax for Julia
MIT License
2 stars 0 forks source link

"natural" ranges #2

Open bjarthur opened 1 month ago

bjarthur commented 1 month ago

natural in the sense of NaturalSort, where the step sizes are adjusted such that the elements come out in nice round numbers, like european currency. went looking, couldn't find a package, so quickly whipped up an iterator that would generate 1,2,5,10,20,50... would submit a PR here, but think perhaps this would best live elsewhere, perhaps on in it's own package. or did i miss sth somewhere? what do you think? i could see making another for 1,3,10,30,100,300...

_strip0(x) = (while x >= 10;  x = div(x,10);  end;  return x)
struct Range125{T} <: AbstractRange{T} 
    start::T
    stop::T
    function Range125(start, stop)
        in(_strip0(start), (1,2,5)) && in(_strip0(stop), (1,2,5)) || 
                error("start and stop must begin with 1, 2, or 5 and the rest of the digits if any must all be 0")
        new{typeof(start)}(start, stop)
    end 
end 
Base.first(r::Range125) = r.start
Base.last(r::Range125) = r.stop
Base.isempty(r::Range125) = first(r) > last(r)
Base.length(r::Range125) = round(Int, log10(last(r)/first(r))*3) + 1
Base.iterate(r::Range125) = isempty(r) ? nothing : (first(r), first(r))
function Base.iterate(r::Range125, s)
    s == last(r) && return nothing
    s0 = _strip0(s)
    n = if s0==2 
        div(5s,2)
    else
        2s
    end 
    (n, n) 
end 
function Base.show(io::IO, r::Range125{T}) where {T}
    print(io, "Range125{")
    show(io, T)
    print(io, "}(")
    ioc = IOContext(io, :typeinfo=>T)
    show(ioc, first(r))
    print(io, ", ")
    show(ioc, last(r))
    print(io, ')')
end
r=Range125(1,10)
@assert collect(r)==[1,2,5,10]
mkitti commented 1 month ago

I'm not sure if this is a very serious package. On one hand, we could pack everything here you would like. On the other hand, if you would like people to use it, they might like a dedicated package better.

mkitti commented 1 month ago

Is this really a range though? What makes a range an AbstractRange as opposed to an AbstractArray?