What is the design and proper usage of functions in Base that starts with underscore?

I’ve found HDF5.jl breaks for Vector of String in 1.10.2 (not really, see below). The reason is, Base._memcpy! is removed from julia/base/reinterpretarray.jl, which is used in _type_load in HDF5.jl.
I’ve checked Base._memcpy! is there in 1.9.4, and it works well.
Any thoughts about why it is removed, and whether it is originally designed for internal use only? What methds should packages like HDF5 use in order to avoid such stability issues?

I realised I’ve lock the version of HDF5 in my computer to v0.16.14, and updating it to v0.17.2 can fix this problem. But the question about the design of usage of functions like Base._memcpy! remains, so I’ll leave the post here.

1 Like

Leading underscores mark functions as internal, and can be changed or removed at any time without breaking versions.

Using them in packages isn’t great, but sometimes it’s the easiest/fastest/best way for some reason. So we do it anyway occasionally.

Often it works fine for years, and if we test against nightly builds we can see when a breakage is coming to future versioned releases and fix the problem before that happens, like HDF5.jl seems to have done.


To expand: This is more of a convention. Many functions that are internal don’t have an underscore. But if it has a leading underscore, then it’s definitely not public stable API.

Whether an internal function has an underscore or not is mostly up to how the author of that thing felt that day – e.g. whether that felt like too prominent of a name for something quite internal.

The example you gave is a perfect illustration: reinterpretarray needed access to the llvm memcopy intrinsic. memcpy! would be have been a very good name.

Instead, 1.10 introduced Base.memcpy which is public stable API, presumably after some bikeshedding in the naming.

If the old Base._memcpy! had instead been called Base.memcpy! then it is likely that the name would have stuck without any room for discussing the ideal name.