Unitful.jl icon indicating copy to clipboard operation
Unitful.jl copied to clipboard

Unable to create `range` with `°C` unit

Open tomyun opened this issue 3 years ago • 2 comments
trafficstars

I'm having issues creating a range defined with °C unit (and K for step unit). After trying different approaches, the only working solution was to directly create one using StepRange or StepRangeLen with explicit types. But then it still had an issue with printing.

Is there a better known approach for this? I may open up a PR for at least taking care of the printing issue for now.

  1. StepRange
julia> (1:3)*u"°C"
ERROR: AffineError: an invalid operation was attempted with affine quantities: rem(2 K, 1 °C)
Stacktrace:
 [1] _affineerror(::Function, ::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, nothing}}, ::Vararg{Any})
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:98
 [2] rem(x::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, nothing}}, y::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}})
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:115
 [3] steprange_last
   @ ./range.jl:346 [inlined]
 [4] StepRange
   @ ./range.jl:316 [inlined]
 [5] StepRange
   @ ./range.jl:369 [inlined]
 [6] *(r::UnitRange{Int64}, y::Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}})
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/range.jl:141
 [7] top-level scope
   @ REPL[27]:1
  1. StepRangeLen
julia> (1:1.0:3)*u"°C"
Error showing value of type StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64}:
ERROR: AffineError: an invalid operation was attempted with affine quantities: 1.0 °C*0
Stacktrace:
  [1] *(x::Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, y::Int64)
    @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:34
  [2] *(y::Int64, x::Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}})
    @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:32
  [3] unsafe_getindex
    @ ./twiceprecision.jl:500 [inlined]
  [4] first(r::StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64})
    @ Base ./range.jl:818
  [5] show(io::IOContext{Base.TTY}, r::StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64})
    @ Unitful ~/.julia/packages/Unitful/SUQzL/src/display.jl:149
  [6] show(io::IOContext{Base.TTY}, #unused#::MIME{Symbol("text/plain")}, r::StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64})
    @ Base ./show.jl:11
  [7] (::REPL.var"#43#44"{REPL.REPLDisplay{REPL.LineEditREPL}, MIME{Symbol("text/plain")}, Base.RefValue{Any}})(io::Any)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:267
  [8] with_repl_linfo(f::Any, repl::REPL.LineEditREPL)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:521
  [9] display(d::REPL.REPLDisplay, mime::MIME{Symbol("text/plain")}, x::Any)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:260
 [10] display(d::REPL.REPLDisplay, x::Any)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:272
 [11] display(x::Any)
    @ Base.Multimedia ./multimedia.jl:328
 [12] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [13] invokelatest
    @ ./essentials.jl:726 [inlined]
 [14] print_response(errio::IO, response::Any, show_value::Bool, have_color::Bool, specialdisplay::Union{Nothing, AbstractDisplay})
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:296
 [15] (::REPL.var"#45#46"{REPL.LineEditREPL, Pair{Any, Bool}, Bool, Bool})(io::Any)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:278
 [16] with_repl_linfo(f::Any, repl::REPL.LineEditREPL)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:521
 [17] print_response(repl::REPL.AbstractREPL, response::Any, show_value::Bool, have_color::Bool)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:276
 [18] (::REPL.var"#do_respond#66"{Bool, Bool, REPL.var"#77#87"{REPL.LineEditREPL, REPL.REPLHistoryProvider}, REPL.LineEditREPL, REPL.LineEdit.Prompt})(s::REPL.LineEdit.MIState, buf::Any, ok::Bool)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:857
 [19] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [20] invokelatest
    @ ./essentials.jl:726 [inlined]
 [21] run_interface(terminal::REPL.Terminals.TextTerminal, m::REPL.LineEdit.ModalInterface, s::REPL.LineEdit.MIState)
    @ REPL.LineEdit /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/LineEdit.jl:2510
 [22] run_frontend(repl::REPL.LineEditREPL, backend::REPL.REPLBackendRef)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:1248
 [23] (::REPL.var"#49#54"{REPL.LineEditREPL, REPL.REPLBackendRef})()
    @ REPL ./task.jl:484

In this case, an instance of StepRangeLen is actually created, but cannot be printed, collected, etc.

julia> r = (1:1.0:3)*u"°C";

julia> typeof(r)
StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64}

julia> r
Error showing value of type StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64}:
ERROR: AffineError: an invalid operation was attempted with affine quantities: 1.0 °C*0
Stacktrace:
  [1] *(x::Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, y::Int64)
    @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:34
  [2] *(y::Int64, x::Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}})
    @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:32
  [3] unsafe_getindex
    @ ./twiceprecision.jl:500 [inlined]
  [4] first(r::StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64})
    @ Base ./range.jl:818
  [5] show(io::IOContext{Base.TTY}, r::StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64})
    @ Unitful ~/.julia/packages/Unitful/SUQzL/src/display.jl:149
  [6] show(io::IOContext{Base.TTY}, #unused#::MIME{Symbol("text/plain")}, r::StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64})
    @ Base ./show.jl:11
  [7] (::REPL.var"#43#44"{REPL.REPLDisplay{REPL.LineEditREPL}, MIME{Symbol("text/plain")}, Base.RefValue{Any}})(io::Any)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:267
  [8] with_repl_linfo(f::Any, repl::REPL.LineEditREPL)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:521
  [9] display(d::REPL.REPLDisplay, mime::MIME{Symbol("text/plain")}, x::Any)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:260
 [10] display(d::REPL.REPLDisplay, x::Any)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:272
 [11] display(x::Any)
    @ Base.Multimedia ./multimedia.jl:328
 [12] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [13] invokelatest
    @ ./essentials.jl:726 [inlined]
 [14] print_response(errio::IO, response::Any, show_value::Bool, have_color::Bool, specialdisplay::Union{Nothing, AbstractDisplay})
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:296
 [15] (::REPL.var"#45#46"{REPL.LineEditREPL, Pair{Any, Bool}, Bool, Bool})(io::Any)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:278
 [16] with_repl_linfo(f::Any, repl::REPL.LineEditREPL)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:521
 [17] print_response(repl::REPL.AbstractREPL, response::Any, show_value::Bool, have_color::Bool)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:276
 [18] (::REPL.var"#do_respond#66"{Bool, Bool, REPL.var"#77#87"{REPL.LineEditREPL, REPL.REPLHistoryProvider}, REPL.LineEditREPL, REPL.LineEdit.Prompt})(s::REPL.LineEdit.MIState, buf::Any, ok::Bool)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:857
 [19] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [20] invokelatest
    @ ./essentials.jl:726 [inlined]
 [21] run_interface(terminal::REPL.Terminals.TextTerminal, m::REPL.LineEdit.ModalInterface, s::REPL.LineEdit.MIState)
    @ REPL.LineEdit /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/LineEdit.jl:2510
 [22] run_frontend(repl::REPL.LineEditREPL, backend::REPL.REPLBackendRef)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:1248
 [23] (::REPL.var"#49#54"{REPL.LineEditREPL, REPL.REPLBackendRef})()
    @ REPL ./task.jl:484

julia> collect(r)
ERROR: AffineError: an invalid operation was attempted with affine quantities: 1.0 °C*0
Stacktrace:
 [1] *(x::Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, y::Int64)
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:34
 [2] *(y::Int64, x::Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}})
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:32
 [3] unsafe_getindex
   @ ./twiceprecision.jl:500 [inlined]
 [4] iterate
   @ ./range.jl:876 [inlined]
 [5] iterate
   @ ./range.jl:874 [inlined]
 [6] vcat
   @ ./range.jl:1354 [inlined]
 [7] collect(r::StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64})
   @ Base ./range.jl:1362
 [8] top-level scope
   @ REPL[33]:1
  1. range()
julia> range(1u"°C", step = 1u"K", length = 3)
ERROR: AffineError: an invalid operation was attempted with affine quantities: -5443//20 °C*2
Stacktrace:
 [1] *(x::Quantity{Rational{Int64}, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, y::Int64)
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:34
 [2] range_start_step_length(a::Quantity{Rational{Int64}, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, step::Quantity{Rational{Int64}, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, len::Int64)
   @ Base ./range.jl:204
 [3] _range(a::Quantity{Rational{Int64}, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, step::Quantity{Rational{Int64}, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, #unused#::Nothing, len::Int64)
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/range.jl:36
 [4] _unitful_start_step_length(start::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, step::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, nothing}}, len::Int64)
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/range.jl:54
 [5] _range(a::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, step::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, nothing}}, #unused#::Nothing, len::Int64)
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/range.jl:50
 [6] range(start::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}; stop::Nothing, length::Int64, step::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, nothing}})
   @ Base ./range.jl:138
 [7] top-level scope
   @ REPL[51]:1

julia> range(1.0u"°C", step = 1u"K", length = 3);

julia> range(1.0u"°C", step = 1u"K", length = 3)
Error showing value of type StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64}:
ERROR: AffineError: an invalid operation was attempted with affine quantities: -272.14999999999986 °C*0
Stacktrace:
  [1] *(x::Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, y::Int64)
    @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:34
  [2] *(y::Int64, x::Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}})
    @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:32
  [3] unsafe_getindex
    @ ./twiceprecision.jl:500 [inlined]
  [4] first(r::StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64})
    @ Base ./range.jl:818
  [5] show(io::IOContext{Base.TTY}, r::StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64})
    @ Unitful ~/.julia/packages/Unitful/SUQzL/src/display.jl:149
  [6] show(io::IOContext{Base.TTY}, #unused#::MIME{Symbol("text/plain")}, r::StepRangeLen{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Base.TwicePrecision{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}, Int64})
    @ Base ./show.jl:11
  [7] (::REPL.var"#43#44"{REPL.REPLDisplay{REPL.LineEditREPL}, MIME{Symbol("text/plain")}, Base.RefValue{Any}})(io::Any)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:267
  [8] with_repl_linfo(f::Any, repl::REPL.LineEditREPL)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:521
  [9] display(d::REPL.REPLDisplay, mime::MIME{Symbol("text/plain")}, x::Any)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:260
 [10] display(d::REPL.REPLDisplay, x::Any)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:272
 [11] display(x::Any)
    @ Base.Multimedia ./multimedia.jl:328
 [12] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [13] invokelatest
    @ ./essentials.jl:726 [inlined]
 [14] print_response(errio::IO, response::Any, show_value::Bool, have_color::Bool, specialdisplay::Union{Nothing, AbstractDisplay})
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:296
 [15] (::REPL.var"#45#46"{REPL.LineEditREPL, Pair{Any, Bool}, Bool, Bool})(io::Any)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:278
 [16] with_repl_linfo(f::Any, repl::REPL.LineEditREPL)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:521
 [17] print_response(repl::REPL.AbstractREPL, response::Any, show_value::Bool, have_color::Bool)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:276
 [18] (::REPL.var"#do_respond#66"{Bool, Bool, REPL.var"#77#87"{REPL.LineEditREPL, REPL.REPLHistoryProvider}, REPL.LineEditREPL, REPL.LineEdit.Prompt})(s::REPL.LineEdit.MIState, buf::Any, ok::Bool)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:857
 [19] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [20] invokelatest
    @ ./essentials.jl:726 [inlined]
 [21] run_interface(terminal::REPL.Terminals.TextTerminal, m::REPL.LineEdit.ModalInterface, s::REPL.LineEdit.MIState)
    @ REPL.LineEdit /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/LineEdit.jl:2510
 [22] run_frontend(repl::REPL.LineEditREPL, backend::REPL.REPLBackendRef)
    @ REPL /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:1248
 [23] (::REPL.var"#49#54"{REPL.LineEditREPL, REPL.REPLBackendRef})()
    @ REPL ./task.jl:484
  1. Direct Instantiation
julia> StepRangeLen(1u"°C", 1u"K", 3, 1)
(5483//20:1:5523//20) K

Above works in a way, but the final unit is fixed to K, not °C.

julia> U = typeof(1u"°C"); S = typeof(1u"K");

julia> r2 = StepRangeLen{U,U,S}(1u"°C", 1u"K", 3, 1)
(1//1:-5443//20:-5433//10) °C

julia> r2 |> collect
3-element Vector{Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}:
 1 °C
 2 °C
 3 °C

This now works as intended, but printing is incorrect. The following example is more easy to see what happens when two units are mixed.

julia> U2 = typeof(1.0u"°C"); S = typeof(1u"K");

julia> r3 = StepRangeLen{U2,U2,S}(1.0u"°C", 1u"K", 3, 1)
(1.0:-272.15:-543.3) °C

It is rather supposed to be (1.0:1.0:3.0) °C. collect() still works fine though. It's more like a printing issue.

julia> r3 |> collect
3-element Vector{Quantity{Float64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}:
 1.0 °C
 2.0 °C
 3.0 °C

The same goes for the case of StepRange.

julia> StepRange(1u"°C", 1u"°C", 3u"°C")
ERROR: AffineError: an invalid operation was attempted with affine quantities: rem(2 K, 1 °C)
Stacktrace:
 [1] _affineerror(::Function, ::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, nothing}}, ::Vararg{Any})
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:98
 [2] rem(x::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, nothing}}, y::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}})
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:115
 [3] steprange_last
   @ ./range.jl:346 [inlined]
 [4] StepRange
   @ ./range.jl:316 [inlined]
 [5] StepRange(start::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, step::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, stop::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}})
   @ Base ./range.jl:369
 [6] top-level scope
   @ REPL[46]:1

julia> StepRange(1u"°C", 1u"K", 3u"°C")
(1//1:-5443//20:3//1) °C

julia> StepRange(1u"°C", 1u"K", 3u"°C") |> collect
3-element Vector{Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}:
 1 °C
 2 °C
 3 °C

julia> StepRange(1u"°C", 1.0u"K", 3u"°C")
(1.0:-272.15:273.15) °C

julia> StepRange(1u"°C", 1.0u"K", 3u"°C") |> collect
3-element Vector{Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}}:
 1 °C
 2 °C
 3 °C
  1. Alternative Syntax
julia> 1u"°C":10u"°C"
ERROR: AffineError: no multiplicative identity for affine quantity 1 °C.
Stacktrace:
 [1] one(x::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}})
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:416
 [2] (::Colon)(start::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, stop::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}})
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/range.jl:131
 [3] top-level scope
   @ REPL[5]:1

julia> 1u"°C":1u"°C":10u"°C"
ERROR: AffineError: an invalid operation was attempted with affine quantities: rem(9 K, 1 °C)
Stacktrace:
 [1] _affineerror(::Function, ::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, nothing}}, ::Vararg{Any})
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:98
 [2] rem(x::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, nothing}}, y::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}})
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/quantities.jl:115
 [3] steprange_last
   @ ./range.jl:346 [inlined]
 [4] StepRange
   @ ./range.jl:316 [inlined]
 [5] StepRange
   @ ./range.jl:369 [inlined]
 [6] _colon
   @ ~/.julia/packages/Unitful/SUQzL/src/range.jl:108 [inlined]
 [7] (::Colon)(start::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, step::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}}, stop::Quantity{Int64, 𝚯, Unitful.FreeUnits{(K,), 𝚯, Unitful.Affine{-5463//20}}})
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/range.jl:106
 [8] top-level scope
   @ REPL[14]:1

julia> 1u"°C":1u"K":10u"°C"
(5483//20:5663//20) K

julia> 1u"°C":1.0u"K":10u"°C"
(274.15:1.0:283.15) K

~None of them works and this is more likely a limitation of Julia parser.~ Range notations with : only work when step values are explicitly provided in K unit, but then they always result into K even start/stop values are °C.

tomyun avatar Aug 30 '22 01:08 tomyun

It would be good to get all of the usual range syntaxes to work with affine units. It does not seem too difficult to add.

1u"°C":0.1u"K":3u"°C" already works but creates values with units K, not °C.

  1. Alternative Syntax
julia> 1u"°C:10u"°C"
ERROR: syntax: cannot juxtapose string literal

The problem with the “alternative syntax” is a missing quote (1u"°C instead of 1u"°C"). I wouldn’t call that a limitation of the Julia parser.

sostock avatar Aug 30 '22 06:08 sostock

Oops, there was a typo. The last part has been updated with new results.

tomyun avatar Aug 30 '22 06:08 tomyun