Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sort on AbstractRange with keywords returns vector #44858

Closed
nick4f42 opened this issue Apr 5, 2022 · 6 comments
Closed

sort on AbstractRange with keywords returns vector #44858

nick4f42 opened this issue Apr 5, 2022 · 6 comments
Labels
sorting Put things in order

Comments

@nick4f42
Copy link

nick4f42 commented Apr 5, 2022

As per #9498, adding any keywords to sort with an AbstractRange makes it call the AbstractVector method and return a vector instead of another range.

julia> versioninfo()
Julia Version 1.7.2
Commit bf53498635 (2022-02-06 15:21 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: AMD Ryzen 7 3700X 8-Core Processor
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-12.0.1 (ORCJIT, znver2)

julia> xs = 1:3
1:3

julia> sort(xs)
1:3

julia> sort(xs, rev=false)
3-element Vector{Int64}:
 1
 2
 3
julia> @which sort(xs)
sort(r::AbstractUnitRange) in Base at range.jl:1304

julia> @which sort(xs, rev=false)
(::Base.var"#sort##kw")(::Any, ::typeof(sort), v::AbstractVector) in Base.Sort at sort.jl:770
@StefanKarpinski
Copy link
Member

The rev keyword could return a range, but any other keyword make that impossible in general.

@nick4f42
Copy link
Author

nick4f42 commented Apr 5, 2022

Then maybe changing the definitions of sort(r) in base/range.jl to something like this?

sort(r::AbstractUnitRange; rev::Bool=false) = rev ? reverse(r) : r
sort(r::AbstractRange; rev::Bool=false) = issorted(r)  rev ? r : reverse(r)

And similarly for sortperm. I'm not sure about sort! though.

@StefanKarpinski
Copy link
Member

Of course that makes the sort function on ranges type unstable, which also isn't good. It seems like the current status quo is the best case already.

@nick4f42
Copy link
Author

nick4f42 commented Apr 5, 2022

This would fix the type instability, but then it doesn't call the generic one when you pass other keyword arguments.

sort(r::AbstractUnitRange) = r

function sort(r::AbstractRange; rev::Bool=false)
    return ifelse(issorted(r)  rev, promote(r, reverse(r))...)
end
julia> sort(-1:1; by=abs)
ERROR: MethodError: no method matching sort(::UnitRange{Int64}; by=abs)
Closest candidates are:
  sort(::AbstractUnitRange) at REPL[1]:1 got unsupported keyword argument "by"
  sort(::AbstractRange; rev) at REPL[2]:1 got unsupported keyword argument "by"
  sort(::AbstractVector; kws...) at sort.jl:770
  ...
Stacktrace:
 [1] kwerr(::NamedTuple{(:by,), Tuple{typeof(abs)}}, ::Function, ::UnitRange{Int64})
   @ Base ./error.jl:163
 [2] top-level scope
   @ REPL[10]:1

It seems like the method in sort.jl should match? Anyways, I'll close the issue if the above won't work.

@vtjnash
Copy link
Member

vtjnash commented Apr 5, 2022

You would need to add kwargs... to the signature, and call isempty(kwargs) || return invoke(sort, Tuple{AbstractVector{T}}, r; rev, kwargs...)

@StefanKarpinski
Copy link
Member

I dunno, it seems like when you sort a range it can't, in general, return a range so we return a vector, which is the best that can be done here. I'm very reluctant to do either introduce a type instability or return a different type based on whether there are any keyword args or not.

@nick4f42 nick4f42 closed this as completed Apr 6, 2022
@LilithHafner LilithHafner added the sorting Put things in order label Jul 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sorting Put things in order
Projects
None yet
Development

No branches or pull requests

4 participants