Catlab.jl
Catlab.jl copied to clipboard
return value of `add_parts!` not interacting well with `set_subpart!`
Hi Catlab team,
I've observed some unexpected behavior when passing the result of add_parts!
to set_subpart!
. I've included an example below, when add_parts!
is adding a single part to an Ob, it returns a 1:1
unit range, which set_subpart!
doesn't like when it is used to set a Hom. However, using only
(or something else) to turn the unit range into an Int gives the desired result.
@present ExSchema(FreeSchema) begin
Ob1::Ob
Ob2::Ob
Fn::Hom(Ob1, Ob2)
end
@acset_type Example(ExSchema, unique_index = [:Fn])
ExampleInstance = Example()
add_parts!(ExampleInstance, :Ob1, 5)
ob2 = add_parts!(ExampleInstance, :Ob2, 1)
set_subpart!(ExampleInstance, 3, :Fn, ob2) # errors, ob2 is 1:1 unit range
set_subpart!(ExampleInstance, 3, :Fn, only(ob2)) # works as expected, converting to Int
I should note this problem only occurs when the result of add_parts!
is a length 1 unit range, the following works fine:
ExampleInstance = Example()
add_parts!(ExampleInstance, :Ob1, 5)
ob2 = add_parts!(ExampleInstance, :Ob2, 2)
set_subpart!(ExampleInstance, [1, 3], :Fn, ob2)
The error occurs in the body of the generated function @assert 0 <= subpart <= acs.obs[$(ob_num(s, s.codoms[f]))]
, since subpart
is a 1:1 unit range. Maybe one of the "higher level" functions in ACSetInterface.jl can deal with this case so the low level setter functions get the right data type?
I'm using Catlab 0.13.7
@epatters I just did some checking, adding this overload to CSetDataStructures.jl allows the preceding example to run as expected, and also does not cause any of the currently existing tests in the test suite to fail.
@inline ACSetInterface.set_subpart!(acs::StructACSet, part::Int, f::Symbol, subpart::T) where {T <: AbstractRange} =
_set_subpart!(acs, part, Val{f}, length(subpart) > 1 ? subpart : only(subpart))
closing this issue, as it was a result of misunderstanding how to interact with the ACSet interface i.e; set_subpart!(ExampleInstance, [3], :Fn, ob2)
works fine with the example code.