How to turn this code snippet into a "callable struct with functions"?

Hi,

My first Julia code below is a simple array-based priority queue with some performance tests for push and pop.
Next step would be to make this into something callable like

pq1 = pq(Float64,Any)
push_pq!(pq1, 1.1, 2.3)
push_pq!(pq1, 1.2, “toto”)
(t, data) = pop_pq!(pq1)

Looking at PriorityQueue.jl blows my mind. There must be something more concise to start with.
I was looking around but did not find this topic treated, maybe missing the right word for it.

Any kind soul to help me with the missing link?

lockerKeys = Int32[]              # locker keys
data = Any[]                      # locker contents
events = Tuple{Float64, Int16}[]  # event array (time, lockerKey)

function push_pq!(t, d)
    # add event to priority queue
    len = length(events)
    # locker keys run from 1:n
    if length(lockerKeys) < len + 1
        push!(lockerKeys, len + 1)
    end
     # store event data in locker array
    key = lockerKeys[len + 1]
    if length(data) < len + 1
        push!(data, d)
    else
        data[key] = d
    end
    # insert (time, key) in priority queue
    left = 1
    right = len
    while left <= right
        mid = div(left + right, 2)
        if events[mid][1] > t
            right = mid - 1
        else
            left = mid + 1
        end
    end
    insert!(events, left, (t, key))
end

function pop_pq!()
    # remove earliest event from priority queue
    (t, key) = popfirst!(events)
    # return key
    lockerKeys[length(events) + 1] = key
    return (t, data[key])
end

#########################################################

function testm(m, n)
    # run pq with n total and max m pending events
    for i = 1:n
        push_pq!(i + m*rand(), rand());
        if i > m
           (t, d) = pop_pq!();
        end
    end
end

function test1()
    for m = 1:10:100
        @time  testm(m, 1e5)
    end
end

test1()

Something like this?

julia> struct Pq{T1,T2}
         t::Vector{T1}
         data::Vector{T2} 
         Pq(T1,T2) = new{T1,T2}(T1[],T2[])
       end

julia> function push_pq!(pq::Pq,t,data)
         push!(pq.t,t)
         push!(pq.data,data)
         return pq
       end
push_pq! (generic function with 1 method)

julia> pop_pq!(pq::Pq) = (pq.t,pq.data)
pop_pq! (generic function with 1 method)

julia> pq1 = Pq(Float64,Any)
Pq{Float64, Any}(Float64[], Any[])

julia> pq1 = Pq(Float64,Any)
Pq{Float64, Any}(Float64[], Any[])

julia> push_pq!(pq1,1.1,2.3)
Pq{Float64, Any}([1.1], Any[2.3])

julia> push_pq!(pq1,1.2,"toto")
Pq{Float64, Any}([1.1, 1.2], Any[2.3, "toto"])

julia> t, data = pop_pq!(pq1)
([1.1, 1.2], Any[2.3, "toto"])

julia> t
2-element Vector{Float64}:
 1.1
 1.2

julia> data
2-element Vector{Any}:
 2.3
  "toto"

(this is not a “callable struct”, but it could be, but that is something else).

disclaimer: I just followed the initial “target” behavior, the actual code was too complicated :grimacing: . If this is not what you were asking, I’m sorry.

Hi Leandro,

thank you so much, working.

Now I have to figure out how to make this function known “elsewhere”.
load(“my_pq.jl”)
appears to do the job.

Soo much simpler with Matlab (path, function name = file name).
Need definitively more examples to bridge these gaps.
How to learn these aspects of Julia?

Thx again.

https://julialang.org/learning/

(Or here for specific questions)

no more excuses :slight_smile: