-
Notifications
You must be signed in to change notification settings - Fork 1
2022 05 09 report
I was diverted a bit by a remaining failing case in processing and worked mostly
on it. This is a curious one, at least, I didn’t know before that Julia allows
overloading the function call operator. In a nutshell, if you define a structure
S
with an integer field, you then can define something like:
function (s::S)(x::Int)
print("Hi $x+$s.x!")
end
which will make any object if type S
callable (e.g. (S(2)(3)
will print Hi
5!
).
I currently can’t see how to feed this kind of thing to Julia’s type inference. This should be possible, but it seems like esoteric enough corner of the language that there’s not much documentation of it and also it’s quite rare (I found it only once in the 10 packages), so I currently skip it.
One of the 10 packages, DifferentialEquations
, deviate from the usual Julia
pattern when a package X
has the main module named X
. DifferentialEquations
doesn’t have the correspondingly named module, and instead provides several
specific modules. I have to work around such packages manually, and I added
some code to handle this. In the type-stability paper this wasn’t as critical,
as we basically scraped all the data we could find after a test suite was
executed, but here I need a specific module to iterate over. Unfortunately,
there’s no (simple) way to programmatically find out which modules are exported
from a package, so it has to be hardcoded, I believe. And right now I only
process exactly one module per package (a fairer deal would be to process “all
manually hard-coded” modules in a package).
Below are the numbers I currently have. These are along the lines we discussed last week I believe: a fair number of things (“~50% on average across packages”) are deemed stable (look at columns 2 and 3).
Module | Methods | Stable | Unstable | Any | Vararg | Generic | TcFail | NoFuel |
---|---|---|---|---|---|---|---|---|
DifferentialEquations | 1404 | 601 | 3 | 697 | 45 | 54 | 2 | 2 |
Flux | 561 | 114 | 1 | 191 | 102 | 151 | 0 | 2 |
Gadfly | 454 | 277 | 24 | 60 | 44 | 47 | 0 | 2 |
Gen | 997 | 486 | 22 | 293 | 3 | 191 | 0 | 2 |
Genie | 113 | 84 | 6 | 14 | 3 | 6 | 0 | 0 |
IJulia | 174 | 101 | 8 | 54 | 6 | 0 | 0 | 5 |
JuMP | 696 | 372 | 36 | 167 | 11 | 103 | 2 | 5 |
Knet | 160 | 39 | 2 | 66 | 24 | 29 | 0 | 0 |
Plots | 1711 | 673 | 142 | 478 | 226 | 173 | 2 | 17 |
Pluto | 265 | 146 | 28 | 63 | 16 | 9 | 0 | 3 |
After talking to you and looking into my code some more, I realized I didn’t convey all the truth about these numbers. The Stable statistics allow some omissions due to existentials, so it’s not bullet-proof stable. E.g. if I can’t enumerate something because descending down the lattice I hit into an unbounded existential, I simply record that fact in raw results and proceed with other branches of the lattice. I haven’t figured how to incorporate information about these omissions in a digestable way into the aggregate table. I’m thinking, I may need a separate table for Stable methods. What do you think?
I believe we came up roughly with two ideas about analyzing Any
-signatures
last time: 1) manually sample them and try to spot any pattern; 2) pull up
results of dynamic analysis and see what it has to say about those methods
(their instances).
One thing we discussed but weren’t satisfied with is the possibility to
enumerate some concrete types starting from Any
. This suffers from possibly
being too imprecise and not adding much to what is already there.