-
Notifications
You must be signed in to change notification settings - Fork 111
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
How to get a parseable unit string #412
Comments
I put a lenient parser here. This uses an unregistered fork of Unitful, but should be easily adaptable. It's lenient with regards to space or no space between number and unit. |
...also lenient with regards to brackets. It's used for parsing output from proprietary applications with various formats.
|
Same question here! julia> u"angstrom^3"
ų
julia> uparse("ų")
ERROR: ArgumentError: Symbol ų could not be found in unit modules Module[Unitful]
Stacktrace:
[1] lookup_units(unitmods::Vector{Module}, sym::Symbol)
@ Unitful ~/.julia/packages/Unitful/1t88N/src/user.jl:581
[2] lookup_units
@ ~/.julia/packages/Unitful/1t88N/src/user.jl:593 [inlined]
[3] uparse(str::String; unit_context::Module)
@ Unitful ~/.julia/packages/Unitful/1t88N/src/user.jl:536
[4] uparse(str::String)
@ Unitful ~/.julia/packages/Unitful/1t88N/src/user.jl:535
[5] top-level scope
@ REPL[5]:1 This is not helpful when I want to serialize a quantity with units into a JSON or YAML file, then reconstruct it from that file later. |
Bump. Is there any update on this? I don't necessarily need a unit string that can be parsed by Julia. But I would like a unit string that can at least be parsed by E.g. currently none of these work: julia> a = Unitful.u"mg/dL/dL"
mg dL⁻²
julia> string(a)
"mg dL⁻²"
julia> Unitful.uparse(string(a))
ERROR: Base.Meta.ParseError("extra token \"dL⁻²\" after end of expression")
Stacktrace:
[1] #parse#3
@ ./meta.jl:227 [inlined]
[2] parse(str::String; raise::Bool, depwarn::Bool)
@ Base.Meta ./meta.jl:258
[3] parse
@ ./meta.jl:258 [inlined]
[4] uparse(str::String; unit_context::Module)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[5] uparse(str::String)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[6] top-level scope
@ REPL[6]:1
julia> b = Unitful.mg / Unitful.dL / Unitful.dL
mg dL⁻²
julia> a === b
true
julia> string(b)
"mg dL⁻²"
julia> Unitful.uparse(string(b))
ERROR: Base.Meta.ParseError("extra token \"dL⁻²\" after end of expression")
Stacktrace:
[1] #parse#3
@ ./meta.jl:227 [inlined]
[2] parse(str::String; raise::Bool, depwarn::Bool)
@ Base.Meta ./meta.jl:258
[3] parse
@ ./meta.jl:258 [inlined]
[4] uparse(str::String; unit_context::Module)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[5] uparse(str::String)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[6] top-level scope
@ REPL[10]:1
julia> repr(a)
"mg dL⁻²"
julia> repr(b)
"mg dL⁻²"
julia> Unitful.uparse(repr(a))
ERROR: Base.Meta.ParseError("extra token \"dL⁻²\" after end of expression")
Stacktrace:
[1] #parse#3
@ ./meta.jl:227 [inlined]
[2] parse(str::String; raise::Bool, depwarn::Bool)
@ Base.Meta ./meta.jl:258
[3] parse
@ ./meta.jl:258 [inlined]
[4] uparse(str::String; unit_context::Module)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[5] uparse(str::String)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[6] top-level scope
@ REPL[13]:1
julia> Unitful.uparse(repr(b))
ERROR: Base.Meta.ParseError("extra token \"dL⁻²\" after end of expression")
Stacktrace:
[1] #parse#3
@ ./meta.jl:227 [inlined]
[2] parse(str::String; raise::Bool, depwarn::Bool)
@ Base.Meta ./meta.jl:258
[3] parse
@ ./meta.jl:258 [inlined]
[4] uparse(str::String; unit_context::Module)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[5] uparse(str::String)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[6] top-level scope
@ REPL[14]:1 |
I don’t think this is easily possible right now, since there is no way to recover the symbol that a unit is bound to just from its value. For example, in UnitfulAtomic.jl there is a unit |
One way would be to provide a utility function that converts a unit to a parseable unit string, something like "parseableString(vunit)" |
Any news here? To repeat the most important information: My current bad implementation is
|
One way would be to return a string of the actual representation of the unit: julia> str = parseable(u"km^2") # this function does not exist yet
"FreeUnits{(Unit{:Meter, Dimensions{(Dimension{:Length}(1),)}()}(3, 2),), Dimensions{(Dimension{:Length}(2),)}(), nothing}()"
julia> Unitful.eval(Meta.parse(str))
km^2
julia> ans === u"km^2"
true Right now, parsing such a string does work with julia> uparse(str)
ERROR: ArgumentError: FreeUnits{(Unit{:Meter, Dimensions{(Dimension{:Length}(1),)}()}(3, 2),), Dimensions{(Dimension{:Length}(2),)}(), nothing} is not a valid function call when parsing a unit.
Only the following functions are allowed: [:*, :/, :^, :sqrt, :√, :+, :-, ://] |
It seems that only I am currently trying to create a package called UnitfulParsabelString.jl, which will allow me to add a parsable string without breaking Unitful by defining julia> using Unitful, UnitfulParsableString # <- my package
julia> a = u"mg/dL/dL"
mg dL⁻²
julia> string(a)
"mg*dL^-2"
julia> string(a) |> uparse
mg dL⁻²
julia> b = u"angstrom^3"
ų
julia> string(b)
"Å^3"
julia> string(b) |> uparse
ų
julia> c = 1.0u"m*kg/s^2"
1.0 kg m s⁻²
julia> string(c)
"1.0(kg*m*s^-2)"
julia> string(c) |> uparse
1.0 kg m s⁻² Is there a demand for this package? |
This problem may be solved by specifying the function uparse(str; unit_context=Unitful)
ex = Meta.parse(str)
eval(lookup_units(unit_context, ex))
end |
Yes, there is a demand for such a package (e.g. whenever something needs to be stored on file in a standardized format such as JSON). So, I highly appreciate if you can provide such a package (it would be even better, if it would be part of Unitful.jl). All your examples looks good. I am just a bit surprised for:
that this can be parsed with uparse. I checked, and indeed this works with Unitful.jl. |
@MartinOtter You have encouraged me to complete the package to the point where I am satisfied with it. (@v1.8) pkg > add https://github.com/michikawa07/UnitfulParsableString.jl |
I have the following problem:
The reason is that string(unit(v)) returns a string that cannot be parsed. In Julia this seems to be an unusual behavior because string(something) typically returns a string representation of something that can be again parsed by Julia.
I searched extensively in Unitful documentation and the Issues but did not find a solution.
I currently use a bad hack (that most likely does not work in all situations), by replacing " " by "*":
Help is appreciated
The text was updated successfully, but these errors were encountered: