splice! inconsistency with Vector{Vector{UInt8}}

76 views
Skip to first unread message

George Marrows

unread,
Jul 23, 2016, 2:58:10 PM7/23/16
to julia-users
Hi. As per the docs on splice! and n:(n-1) ranges, the following works fine to insert a value before location 1 in a Vector:
x = [1,2,3]
splice!(x, 1:0, 23)
print(x)  # => [23,1,2,3]

But the following behaves strangely and seems to corrupt the array in the process:
a = Vector{UInt8}[UInt8[0xf3,0x32,0x37]]
splice!(a, 1:0, UInt8[7,3])   # =>  MethodError: `convert` has no method matching convert(::Type{Array{UInt8,1}}, ::UInt8)
print(a) # => [#undef,#undef,UInt8[0xf3,0x32,0x37]]

Is this a bug, or have I simply not read the docs correctly?

Many thanks,
George

Milan Bouchet-Valat

unread,
Jul 25, 2016, 8:40:47 AM7/25/16
to julia...@googlegroups.com
Le samedi 23 juillet 2016 à 11:37 -0700, 'George Marrows' via julia-
users a écrit :
> Hi. As per the docs on splice! and n:(n-1) ranges, the following
> works fine to insert a value before location 1 in a Vector:
> x = [1,2,3]
> splice!(x, 1:0, 23)
> print(x)  # => [23,1,2,3]
This example works, but only as a special-case of '23' being taken as
equivalent to '[23]'.

> But the following behaves strangely and seems to corrupt the array in
> the process:
> a = Vector{UInt8}[UInt8[0xf3,0x32,0x37]]
> splice!(a, 1:0, UInt8[7,3])   # =>  MethodError: `convert` has no
> method matching convert(::Type{Array{UInt8,1}}, ::UInt8)
> print(a) # => [#undef,#undef,UInt8[0xf3,0x32,0x37]]
This example fails because 'a' is a vector of vectors, so you need to
pass a vector of vectors to splice!() too. Since you pass it a vector
of UInt8, it tries to insert UInt8 values into a, which isn't possible.
The failure comes from 'convert(Vector{UInt8}, 7)'.

Try with
splice!(a, 1:0, Vector{UInt8}[UInt8[7,3]])

The array corruption is a different issue which is hard to fix:
checking whether conversion will succeed before resizing the array
hurts performance a lot, so currently if conversion fails the array is
resized anyway. This might be fixed at some point if a good solution is
found. See https://github.com/JuliaLang/julia/issues/15868


Regards

George Marrows

unread,
Jul 25, 2016, 9:23:23 AM7/25/16
to julia-users
To answer myself: I didn't read the docs correctly. Or I got my types mangled. Or both.

The final splice should be
  splice!(a, 1:0, Vector{UInt8}[UInt8[7,3]])
not
  splice!(a, 1:0, UInt8[7,3])

splice! splices in another collection, not a single element.

Interfaces are very informally defined in Julia aren't they? I don't see there's any way to name an iterable something so that the def of splice! could be eg
  function splice!{E, T<:Integer}(a::Vector{E}, r::UnitRange{T}, ins::Iterable{E})
... which would have helped me not to trip over this problem

George
Reply all
Reply to author
Forward
0 new messages