define vector-median(vec)
  ;; main quick-select algorithm
  define quick-select(vec l r k)
    define partition(vec l r pivot)
      ;; swap elements
      define swap(vec i1 i2)
        define l vector-ref(vec i1)
        vector-set! vec i1 vector-ref(vec i2)
        vector-set! vec i2 l
      ;; main partition code
      define value vector-ref(vec pivot)
      define sidx l
      swap(vec pivot r)
      while {l < r}
        if {vector-ref(vec l) < value}
          begin
            swap vec l sidx
            inc! sidx
        inc! l
      swap vec sidx r
      sidx
    ;; main quickselect code
    if {l = r}
      then
        vector-ref(vec k)
      else
        let*  ;; Miho avoids creating lambda for this
          \\
            pivot {{r + 1 + l} div 2}
            new-pivot partition(vec l r pivot)
            diff {new-pivot - l}
          cond
            {k = diff}
              vector-ref(vec new-pivot)
            {k < diff}
              quick-select(vec l {new-pivot - 1} k)
            else
              quick-select(vec {new-pivot + 1} r {k - diff - 1})
  ;; we don't need fully sorted vector, so perform partition sort only
  let <* vlen vector-length(vec) *>  ;; still no lambda
    if {odd? vlen}
      then
        quick-select(vec 0 {vlen - 1} {vlen div 2})
      else
        (div (+ quick-select(vec 0 {vlen - 1} {{vlen div 2} - 1})
                quick-select(vec 0 {vlen - 1} {vlen div 2}))
             2)
