# Static.jl vs StaticNumbers.jl

**URL:** https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228
**Category:** Tooling
**Created:** [September 13, 2022, 6:27pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228 "2022-09-13T18:27:00Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![cscherrer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cscherrer/32/7631_2.png) [@cscherrer](https://discourse.julialang.org/u/cscherrer)
#### Post date: [September 13, 2022, 6:27pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/1 "2022-09-13T18:27:00Z")

</div>

I recently learned that there’s a [StaticNumbers.jl](https://perrutquist.github.io/StaticNumbers.jl/dev/index.html) from @Per that seems very similar to the SciML [Static.jl](https://github.com/SciML/Static.jl) (mostly actively @Zach_Christensen).

Are there known tradeoffs between these? Could there be a possibility to get the best of both in a single package?

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [September 14, 2022, 1:55am UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/2 "2022-09-14T01:55:22Z")

</div>

I can see from the code that StaticNumbers does things like subtyping Integers which then invalidates a ton of Base functionality. This is something Static.jl used to do, until we realized it contributed more than 2 seconds to load time IIRC, so that was cut out.

Static.jl is really just trying to be a very practical package, looking at the current landscape, and doing as much as it can and being as nice as it can without hitting absurd levels of invalidation and recompilation. Because of that, it makes a few trade-offs. That said, the older versions of Static.jl which does all of the nice things (a few more than StaticNumbers.jl seems to do) added over 8 seconds to load times for OrdinaryDiffEq.jl, so 🤷 😅 that had to be tamed.

In the end, I think these packages are mostly stopgaps. Better compile support for static handling, such as doing things like making `Val(1) + Val(1) == Val(2)` (i.e. making every operator, if applied with all arguments `Val`, operating on the values statically), is probably what’s required to make this all truly useful in the end. Without it, you need a custom system image.

---

<div class="post-metadata">

### Author: ![Zach\_Christensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zach_christensen/32/7220_2.png) [@Zach\_Christensen](https://discourse.julialang.org/u/Zach_Christensen)
#### Post date: [September 14, 2022, 7:36am UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/3 "2022-09-14T07:36:10Z")

</div>

We also decided early on to be more strict about which numbers would get explicit static type support in Static.jl because there’s not a whole lot of benefit in supporting three different static float types

---

<div class="post-metadata">

### Author: ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)
#### Post date: [September 14, 2022, 8:58am UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/4 "2022-09-14T08:58:04Z")

</div>

StaticNumbers.jl is a lot older than Static.jl, and at the time, there was not so much discussion about invalidations affecting load time. Also, constant propagation in Julia was not nearly as good as it is now. I think it is really cool that something like StaticNumbers.jl is possible to do in Julia, but that’s mostly theoretical, and In practice I tend to use `Val` instead in my own code in the rare cases where constant propagation is not enough.

What I really would wish for in the core language is [a feature that lets you branch on whether a value is known at compile time](https://discourse.julialang.org/t/branch-on-whether-a-value-is-known-to-the-compiler/34850), without having to use a `Static` or `Val` type at all.

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [September 14, 2022, 1:19pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/5 "2022-09-14T13:19:17Z")

</div>

This question was also touched in yesterdays long discussion in the #gripes slack channel (:  
`Static.jl` puts more weight on loading/compilation times, sacrificing some functionality for that. For example, it recently stopped subtyping `static(1) isa Integer`. Meanwhile, `StaticNumbers.jl` still provides static `Integer`s, making them more compatible with generic code. There may be other similar differences as well.

---

<div class="post-metadata">

### Author: ![cscherrer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cscherrer/32/7631_2.png) [@cscherrer](https://discourse.julialang.org/u/cscherrer)
#### Post date: [September 14, 2022, 1:31pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/6 "2022-09-14T13:31:35Z")

</div>

Thanks, I hadn’t seen that. Yeah, the new Static.jl types are unfortunate. In the MeasureTheory ecosystem it forced us to stick to 0.6, mostly because we need things like `static(0.3) isa Real` and `static(3) isa Integer`.

From the Slack discussion it seems like a lot of other people might be in the same boat. Maybe we could get a registered fork with proper subtyping?

---

<div class="post-metadata">

### Author: ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)
#### Post date: [September 14, 2022, 1:35pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/7 "2022-09-14T13:35:35Z")

</div>

Maybe also worth mentioning here; the new `@assume_effects` macro can be used to enable very aggressive constant-propagation in some cases. For example:

```julia
# Example function
fib(n) = n<=2 ? 1 : fib(n-1) + fib(n-2)

# Make fib(::Val) compute at compile-time
Base.@assume_effects :terminates_globally fib(::Val{N}) where {N} = fib(N)

# Check the result
@code_llvm fib(Val(40)) # ret i64 102334155

```

---

<div class="post-metadata">

### Author: ![cscherrer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cscherrer/32/7631_2.png) [@cscherrer](https://discourse.julialang.org/u/cscherrer)
#### Post date: [September 14, 2022, 1:38pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/8 "2022-09-14T13:38:41Z")

</div>

Sure, but sometimes we really need type-level values. Some discussion of that in

> [@Constant propagation vs generated functions](https://discourse.julialang.org/t/constant-propagation-vs-generated-functions/83788):
>
> Before getting started in Julia, I did most of my work in Haskell. It’s a great language, but a few things kept causing me trouble: The strong PL focus of the community was great, but it seemed to come at a cost of concern about numerical algorithms. I really need both. The type system is amazing, but PPL tends to push this to its limits. Doing anything new seemed to turn into a type theory research effort, which isn’t really my thing. There’s a “Template Haskell” for metaprogramming, but it’s…

On the question of invalidations… If there’s a library that’s shown to be useful but can’t meet some performance criteria (invalidations causing long load times), that seems like evidence of a fundamental language problem. Especially for a language as performance-oriented as Julia, I’d think either there a fast way to do something, or Julia should adapt to _enable_ a fast way to do it.

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [September 14, 2022, 2:00pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/9 "2022-09-14T14:00:38Z")

</div>

> [@cscherrer](#):
>
> From the Slack discussion it seems like a lot of other people might be in the same boat. Maybe we could get a registered fork with proper subtyping?

For me, `StaticNumbers` turned out to be enough, but the fork idea also sounds good. In principle, one could stay on an older version of `Static` forever, but this would likely lead to conflicts given `Static.jl` many dependents.

---

<div class="post-metadata">

### Author: ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)
#### Post date: [September 14, 2022, 2:55pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/10 "2022-09-14T14:55:08Z")

</div>

We won’t be able to depend on any package using StaticNumbers without destroying our hard work improving load times.

---

<div class="post-metadata">

### Author: ![cscherrer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cscherrer/32/7631_2.png) [@cscherrer](https://discourse.julialang.org/u/cscherrer)
#### Post date: [September 14, 2022, 3:13pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/11 "2022-09-14T15:13:18Z")

</div>

This is why I think it’s not an ecosystem issue, but a fundamental language issue. MeasureTheory needs this functionality, but of course we don’t want the load time issues (though I haven’t seen any such issues so far).

EDIT: What we mostly need is `StaticFloat64 <: Real`, since sooo many functions in the wild have `::Real` constraints. We could _maybe_ work around the current limitation, but it would be extremely hacky. More discussion here:

> <https://github.com/SciML/Static.jl/issues/66>
>
> Now that \`StaticFloat64 \<: Real\` is false, lots of functions that are defined in…dependently of Static.jl are breaking. More concretely, suppose
> \`\`\`julia
> foo(x::Real)
> \`\`\`
> is defined in a package that does \_not\_ depend on Static.jl. Passing a \`StaticFloat64\` to \`foo\` now throws an \`MethodError\`. 
> 
> For packages I control, there's an easy fix: Change the constraint to \`::Number\` or remove it altogether. But what's the recommended approach for packages I can't change so easily?
> 
> The only easy fix I see is to define a local \`\_foo(x) = foo(x)\`, add a method \`\_foo(::StaticFloat64{x}) where {x}\`, and then always call \`\_foo\`. But that seems like a mess, and it will still break downstream when users of \_my\_ package try to call \`foo\`. Any other ideas?

---

<div class="post-metadata">

### Author: ![Zach\_Christensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zach_christensen/32/7220_2.png) [@Zach\_Christensen](https://discourse.julialang.org/u/Zach_Christensen)
#### Post date: [September 14, 2022, 3:15pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/12 "2022-09-14T15:15:34Z")

</div>

The current intention of constant propagation does not cover the full utility of static values. I did a long winded explanation and demonstration of this here [Create staticint.jl by Tokazama · Pull Request #44538 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/44538#issuecomment-1229205583). The short version is that `@assume_effects` and more aggressive constant propagation won’t ever be a full substitute for static values.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [September 14, 2022, 4:14pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/13 "2022-09-14T16:14:00Z")

</div>

> [@cscherrer](#):
>
> This is why I think it’s not an ecosystem issue, but a fundamental language issue.

Agreed. What you really want just isn’t possible in a package right now. It needs compiler support or it has to be in the system image unless you are willing to sacrifice all precompilation. That’s a more fundamental language issue that these packages won’t be able to solve.

---

<div class="post-metadata">

### Author: ![Zach\_Christensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zach_christensen/32/7220_2.png) [@Zach\_Christensen](https://discourse.julialang.org/u/Zach_Christensen)
#### Post date: [September 14, 2022, 4:18pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/14 "2022-09-14T16:18:46Z")

</div>

We could do a separate package that is `StatocFloats` because most of the load time issues for packages depend on `StaticInt`

---

<div class="post-metadata">

### Author: ![cscherrer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cscherrer/32/7631_2.png) [@cscherrer](https://discourse.julialang.org/u/cscherrer)
#### Post date: [September 14, 2022, 4:19pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/15 "2022-09-14T16:19:57Z")

</div>

> [@ChrisRackauckas](#):
>
> It needs compiler support or it has to be in the system image unless you are willing to sacrifice all precompilation.

@Zach_Christensen has already mentioned [his PR around this](https://github.com/JuliaLang/julia/pull/44538), which I hope can move forward. Do you think static floats will also need base support, or could there be a path toward `StaticFloat64 <: Real` in a library without invalidation issues?

EDIT: Zach beat me to the punch 🙂

---

<div class="post-metadata">

### Author: ![cscherrer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cscherrer/32/7631_2.png) [@cscherrer](https://discourse.julialang.org/u/cscherrer)
#### Post date: [September 14, 2022, 4:22pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/16 "2022-09-14T16:22:30Z")

</div>

A StaticFloats.jl would help a lot! I think I could make due with the `StaticInt` support in Static.jl until there’s Base support for that

---

<div class="post-metadata">

### Author: ![Zach\_Christensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zach_christensen/32/7220_2.png) [@Zach\_Christensen](https://discourse.julialang.org/u/Zach_Christensen)
#### Post date: [September 14, 2022, 4:32pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/17 "2022-09-14T16:32:06Z")

</div>

Invalidations are pretty hard to predict for something as fundamental as floats and integers. It’s usually easier to solve for floats because they aren’t involved in indexing, which is everywhere (indexing related behavior is probably 90% of what we use `StaticInt` for too ☹). The implementation of `StaticFloat4` can be completely independent if we subtype `Real`, but then it is kind of obnoxious for Static.jl to continue to grow in size (and load time) when it was never intended to be a very large package.

---

<div class="post-metadata">

### Author: ![cscherrer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cscherrer/32/7631_2.png) [@cscherrer](https://discourse.julialang.org/u/cscherrer)
#### Post date: [September 14, 2022, 4:34pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/18 "2022-09-14T16:34:43Z")

</div>

Right, so maybe there should be a new StaticFloats.jl owning StaticFloat64, and that code is removed form Static.jl?

---

<div class="post-metadata">

### Author: ![Zach\_Christensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zach_christensen/32/7220_2.png) [@Zach\_Christensen](https://discourse.julialang.org/u/Zach_Christensen)
#### Post date: [September 14, 2022, 4:51pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/19 "2022-09-14T16:51:58Z")

</div>

It might be the best solution for the time being. We just would need to make sure its a manageable breaking change forst

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [September 14, 2022, 5:23pm UTC](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228/20 "2022-09-14T17:23:45Z")

</div>

> [@ChrisRackauckas](#):
>
> That’s a more fundamental language issue that these packages won’t be able to solve.

For the same reason, adding the code that would be in a package directly into Base via some ststicint.jl file to prevent invalidation is not going to solve the situation, and will, at best, just be a bandaid for one specific usecase. Personally I don’t think that’s a good idea, and the reason can be seen in this very thread: what about floating points values? And then the next “what about” and so on and so on.

[Next page](https://discourse.julialang.org/t/static-jl-vs-staticnumbers-jl/87228.md?page=2)
