rdboyes
November 17, 2023, 8:49pm
1
Hi All -
I’m trying to fix an error introduced in AlgebraOfGraphics by Julia 1.10 and I’m having a hard time understanding what is actually happening. The error is now thrown any time the function AlgebraOfGraphics.density() is used, and I think it’s happening at one of the following lines:
_kde(data::NTuple{1, Any}; kwargs...) = kde(data...; kwargs...)
_kde(data::Tuple; kwargs...) = kde(data; kwargs...)
Base.@kwdef struct DensityAnalysis{D, K, B}
datalimits::D=automatic
npoints::Int=200
kernel::K=automatic
bandwidth::B=automatic
end
# Work around lack of length 1 tuple method
_kde(data::NTuple{1, Any}; kwargs...) = kde(data...; kwargs...)
_kde(data::Tuple; kwargs...) = kde(data; kwargs...)
defaultdatalimits(positional) = map(nested_extrema_finite, Tuple(positional))
applydatalimits(f::Function, d) = map(f, d)
applydatalimits(limits::Tuple, _) = limits
function _density(vs::Tuple; datalimits, npoints, kwargs...)
k = _kde(vs; kwargs...)
intervals = applydatalimits(datalimits, vs)
As a result of the following update to julia: make Tuple{Union{}} unconstructable by vtjnash · Pull Request #49111 · JuliaLang/julia · GitHub
But I’m just kind of lost as to 1. why this change was made and 2. what we’re supposed to do instead. Any help would be appreciated!
jameson
November 17, 2023, 11:49pm
2
Can you post a full stack trace? I don’t see where this is trying to construct Tuple{Union{}} just from looking at it
rdboyes
November 18, 2023, 2:43pm
3
Here’s a (modified) example from the AlgebraOfGraphics tutorial that will trigger the error:
using PalmerPenguins, DataFrames, AlgebraOfGraphics
penguins = dropmissing(DataFrame(PalmerPenguins.load()))
penguin_bill = data(penguins) * mapping(
:bill_length_mm => (t -> t / 10) => "bill length (cm)",
:bill_depth_mm => (t -> t / 10) => "bill depth (cm)",
)
plt = penguin_bill * density(npoints=50) * mapping(col = :species)
axis = (width = 225, height = 225)
draw(plt; axis = axis)
And the resulting stack trace:
ERROR: LoadError: Tuple field type cannot be Union{}
Stacktrace:
[1] map(f::Function, d::Dictionaries.Indices{Union{}})
@ Dictionaries C:\Users\Randy\.julia\packages\Dictionaries\7aBxp\src\map.jl:91
[2] unnest(vs::Vector{@NamedTuple{}}, indices::Dictionaries.Indices{Union{}})
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\algebra\layer.jl:81
[3] unnest_dictionaries(vs::Vector{@NamedTuple{}})
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\algebra\layer.jl:84
[4] map(f::AlgebraOfGraphics.var"#192#193"{@NamedTuple{datalimits::Tuple{Tuple{Float64, Float64}, Tuple{Float64, Float64}}, npoints::Int64}}, processedlayer::ProcessedLayer)
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\algebra\layer.jl:101
[5] (::AlgebraOfGraphics.DensityAnalysis{MakieCore.Automatic, MakieCore.Automatic, MakieCore.Automatic})(input::ProcessedLayer)
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\transformations\density.jl:30
[6] process(layer::Layer)
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\algebra\processing.jl:102
[7] iterate
@ Base .\generator.jl:47 [inlined]
[8] collect(itr::Base.Generator{Layers, typeof(AlgebraOfGraphics.process)})
@ Base .\array.jl:832
[9] map
@ Base .\abstractarray.jl:3301 [inlined]
[10] ProcessedLayers(a::Layer)
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\algebra\layers.jl:41
[11] compute_axes_grid(d::Layer; axis::@NamedTuple{width::Int64, height::Int64}, palettes::@NamedTuple{})
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\algebra\layers.jl:114
[12] compute_axes_grid
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\algebra\layers.jl:110 [inlined]
[13] compute_axes_grid(fig::Makie.Figure, d::Layer; axis::@NamedTuple{width::Int64, height::Int64}, palettes::@NamedTuple{})
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\algebra\layers.jl:100
[14] compute_axes_grid
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\algebra\layers.jl:97 [inlined]
[15] #240
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\draw.jl:21 [inlined]
[16] update
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\draw.jl:10 [inlined]
[17] plot!(fig::Makie.Figure, d::Layer; axis::@NamedTuple{width::Int64, height::Int64}, palettes::@NamedTuple{})
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\draw.jl:21
[18] plot!
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\draw.jl:16 [inlined]
[19] (::AlgebraOfGraphics.var"#244#245"{@NamedTuple{width::Int64, height::Int64}, @NamedTuple{}, @NamedTuple{}, @NamedTuple{}, @NamedTuple{}, Layer})(f::Makie.Figure)
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\draw.jl:48
[20] update
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\draw.jl:10 [inlined]
[21] #draw#243
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\draw.jl:47 [inlined]
[22] top-level scope
@ c:\Users\Randy\.julia\dev\TidierPlots\scratch\density_test.jl:14
in expression starting at c:\Users\Randy\.julia\dev\TidierPlots\scratch\density_test.jl:14
jameson
November 18, 2023, 5:46pm
4
Ah, I see. You should report this bug to Dictionaries then. It is using an unstable private API (Core.Compiler.return_type) and appear to be not fully implementing the Base.map
API correctly (the return type depends on inference. While, I think the usual implementations use @default_eltype
?
Sukera
November 18, 2023, 6:31pm
5
That likely won’t help with getting away from internals:
help?> Base.@default_eltype
│ Warning
│
│ The following bindings may be internal; they may change or be removed in future versions:
│
│ • Base.@default_eltype
No documentation found for private symbol.
which in the end also uses Core.Compiler.return_type
:
julia> @macroexpand Base.@default_eltype([19293])
quote
#= array.jl:743 =#
if [19293] isa Base.Generator && ([19293]).f isa Base.Type
#= array.jl:744 =#
var"#7#T" = ([19293]).f
else
#= array.jl:746 =#
var"#7#T" = (Base.Core).Compiler.return_type(Base._iterator_upper_bound, Base.Tuple{Base.typeof([19293])})
end
#= array.jl:748 =#
Base.promote_typejoin_union(var"#7#T")
end
I think for the case in Dictionaries.jl (link ) there isn’t really anything else to do other than rely on inference. The question is rather - what introduced that Union{}
in the first place, seeing as its also present in the frames before Dictionaries.jl?
Sukera
November 18, 2023, 6:41pm
6
rdboyes:
[4] map(f::AlgebraOfGraphics.var"#192#193"{@NamedTuple{datalimits::Tuple{Tuple{Float64, Float64}, Tuple{Float64, Float64}}, npoints::Int64}}, processedlayer::ProcessedLayer)
@ AlgebraOfGraphics C:\Users\Randy\.julia\packages\AlgebraOfGraphics\yhdjr\src\algebra\layer.jl:101
Looking up the stackframes, I think it’s this that introduces the Union{}
somehow:
function Base.map(f, processedlayer::ProcessedLayer)
axs = shape(processedlayer)
outputs = map(CartesianIndices(axs)) do c
return f(slice(processedlayer.positional, c), slice(processedlayer.named, c))
end
positional, named = unnest_arrays(map(first, outputs)), unnest_dictionaries(map(last, outputs))
return ProcessedLayer(processedlayer; positional, named)
end
I don’t know about the internals of AlgebraOfGraphics, but I think the question is why this causes map(_ , outputs)
to be a Vector{@NamedTuple{}}
.