Git Product home page Git Product logo

Comments (14)

ChrisRackauckas avatar ChrisRackauckas commented on June 10, 2024

Could you have a way to override so a user could do Pkg.build("Unitful",override_defaults=true), and throw an informative error if the defaults are wrong:

Your defaults are bad. If you have recently upgraded, you may need to use `Pkg.build("Unitful",override_defaults=true)`. Warning: This will override user defaults.

This is similar to how in Plots.jl or DifferentialEquations.jl if you try to use a conditional dependency it will give install instructions. Not every time the user needs it, but I think the vast majority of users will find this helpful (and those who are using their own defaults are probably power users who will understand what this error message means anyways)

from unitful.jl.

ajkeller34 avatar ajkeller34 commented on June 10, 2024

For now I will catch errors emitted from include("Defaults.jl"), let the user know that the defaults are bad, and suggest a course of action. I'm hesitant to extend Pkg.build but maybe in the future I could provide a convenience function rm_defaults() or something. Anyways, thanks, will tag and release after CI finishes.

from unitful.jl.

mweastwood avatar mweastwood commented on June 10, 2024

In theory I like the idea that the user may be able to specify their own units, but I strongly believe that this should happen in their .juliarc.jl instead of in deps/Defaults.jl. I want to be able to reliably count on the existence of certain units, because I don't want to distribute code that depends on the "day" unit if is possible that somebody may have deleted that line or changed its definition. I would much prefer the definition of "day" to be fixed.

from unitful.jl.

ChrisRackauckas avatar ChrisRackauckas commented on June 10, 2024

Good point with the .juliarc, that's much more standard.

from unitful.jl.

ajkeller34 avatar ajkeller34 commented on June 10, 2024

I would like to do this in principle but there are a few obstacles:

  • I'm not sure how you guarantee the existence of certain units if you also allow the user the flexibility to choose whatever reference system of units they want. The @unit macro requires a quantity given in terms of previously defined units. If the user wanted non-SI reference units, all subsequent unit definitions would need to change. This may be a niche case, but to maintain current levels of customizability while guaranteeing the user hasn't removed some of the unit definitions is a tall order. Maybe this degree of customization is just totally excessive.
  • What about promotion rules for units? These also need to be defined exactly once to have things function properly and not emit redefinition warnings, but I don't want to require the default behavior. It seems to me that such definitions have to be in Defaults.jl, otherwise I would have to count on the user to add an appropriate definition to .juliarc.jl which is not very nice.
  • At the moment, .juliarc is not precompiled, so that would prevent precompilation of unit definitions (unless the user put all their definitions into a new module and did using UnitDefs or the like in .juliarc.jl). Right now Unitful loads very fast and I'm not eager to change that.

For your specific concern I would check if units are defined and either trust that the user hasn't changed the meaning of it or verify that it has the relationships with other units you require. You can always give an informative error if you find something unexpected.

julia> isdefined(Unitful, :d) && isdefined(Unitful, :𝐓) && dimension(u"d") == u"𝐓"
true

julia> isdefined(Unitful, :s) && isdefined(Unitful, :hr) && 1u"d" == 24u"hr" == 86400u"s"
true

from unitful.jl.

mweastwood avatar mweastwood commented on June 10, 2024

Ah, I see. If I am understanding correctly, you want the user to be able to pick the units specified by the @refunit lines?

What if you could customize your units by writing your own module:

__precompile__()

module MyAwesomeUnits

export fl, fn

using Unitful.Base # pulls in all the macros needed to do this

@dimension 𝐋 "𝐋" Length
@dimension 𝐓 "𝐓" Time
@refunit  fl       "fl"      Furlong     𝐋           true
@refunit  fn       "fn"      Fortnight    𝐓           true

# etc.

end

This would still give the user absolutely full control over their units when they do using MyAwesomeUnits. You could even register this module as a package if you thought your unit system was particularly useful.

Unitful itself could then provide a sane set of default units with using Unitful.Defaults. Or maybe you could even select what system you want from a couple different options. (using Unitful.SIUnits vs using Unitful.CGSUnits).

I think this idea maintains the customizability of the current system, resolves the difficulty of updating deps/Defaults.jl (because this file is no longer needed), and lets using Unitful produce a consistent result across all machines (which is my biggest concern).

from unitful.jl.

mweastwood avatar mweastwood commented on June 10, 2024

For the record, if Unitful was extensible in this way, I would definitely maintain a set of units specific to astronomy in a separate package. In this hypothetical package using AstroUnits would get you cgs units, arcseconds, parsecs, solar radius, solar mass, jupiter mass, etc. This would be a really useful package!

from unitful.jl.

ajkeller34 avatar ajkeller34 commented on June 10, 2024

This is a really intriguing idea. I love that it would facilitate code reuse, solve the occasional breakage of defaults, and make unit system-switching easier.

I'm interested in trying to build this out after some further thought and discussion. I still need to figure out how the unit promotion would work (what about the @preferunit and promote_rule statements?). Also, I guess the @u_str macro would need to change, since that refers to units defined in the Unitful module.

from unitful.jl.

mweastwood avatar mweastwood commented on June 10, 2024

I think MyAwesomeUnits would need to define and export its own @u_str macro in order for using MyAwesomeUnits to do the right thing. I'm not sure whether this is feasible given the implementation of @u_str, but you might be able to do something like:

macro unitful_setup()
    quote
        macro u_str(...)
            # current definition of @u_str
        end
    end
end

Then you would just need to include @unitful_setup at the end of your list of unit definitions.

from unitful.jl.

JeffreySarnoff avatar JeffreySarnoff commented on June 10, 2024

I worked through a similar issue with timezones (some were predefined in an accelerated way by default, others a user could specify to be predefined that way, and the rest were brought in as needed). In that situation, having the Defaults.jl file be as PkgDefaults.jl and using a second file (or module) as e.g. UserDefaults.jl worked alright. It also provided all the support needed for having different sets of defaults (like the AstroUnits example above).

from unitful.jl.

jzuhone avatar jzuhone commented on June 10, 2024

I'm just coming across this package and finding it intriguing.

I'm one of the developers of yt (http://yt-project.org), which has a symbolic unit system. YT.jl (http://hea-www.cfa.harvard.edu/~jzuhone/yt_julia) is the Julia wrapper for yt.

YT.jl's unit handling is here: http://hea-www.cfa.harvard.edu/~jzuhone/yt_julia/users_guide/arrays.html

I'm kind of interested in providing a translation layer between YT.jl and Unitful.jl from within YT.jl--if I come up with something I'll let you know.

yt handles the issue raised here in the Python context by storing all units in a "unit lookup table", which can be added to but has a default set of units:

https://bitbucket.org/yt_analysis/yt/src/ed03447eae86c5b2dd8d9b1d0eadfed0865d2728/yt/units/unit_lookup_table.py?at=yt&fileviewer=file-view-default

That's just a Python dictionary, but it can be added to using yt's unit registry machinery:

https://bitbucket.org/yt_analysis/yt/src/ed03447eae86c5b2dd8d9b1d0eadfed0865d2728/yt/units/unit_registry.py?at=yt&fileviewer=file-view-default

I don't know if a unit lookup table with a registry for adding units is feasible in this context, but it certainly seems like a viable option.

from unitful.jl.

ChrisRackauckas avatar ChrisRackauckas commented on June 10, 2024

yt handles the issue raised here in the Python context by storing all units in a "unit lookup table", which can be added to but has a default set of units:

That's just a Python dictionary, but it can be added to using yt's unit registry machinery:

I don't think Unitful should use dictionaries at all. The purpose for dispatch-based units is that it has no runtime overhead. By design, using dictionaries has runtime checks.

from unitful.jl.

ajkeller34 avatar ajkeller34 commented on June 10, 2024

Happy to say this one is closed. See the "latest" docs for Unitful to understand how this works now. I will write a post on Discourse in the next day or two with some further information. Note that Unitful should now be compatible with both julia 0.5.0 and 0.6.0-dev although there's still plenty of time for it to break before 0.6.0...

@mweastwood, units packages are now possible. See UnitfulUS.jl for an example. The tests there should only be failing because I haven't tagged the new version of Unitful yet.

from unitful.jl.

mweastwood avatar mweastwood commented on June 10, 2024

Yay! Looking forward to trying this out.

from unitful.jl.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.