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

**URL:** <https://discourse.julialang.org/t/what-is-the-design-and-proper-usage-of-functions-in-base-that-starts-with-underscore/112868>\
**Category:** General Usage\
**Created:** [April 12, 2024, 9:34am UTC](https://discourse.julialang.org/t/what-is-the-design-and-proper-usage-of-functions-in-base-that-starts-with-underscore/112868 "2024-04-12T09:34:59Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![jsjie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jsjie/32/22477_2.png) [@jsjie](https://discourse.julialang.org/u/jsjie)\
**Post date:** [April 12, 2024, 9:34am UTC](https://discourse.julialang.org/t/what-is-the-design-and-proper-usage-of-functions-in-base-that-starts-with-underscore/112868/1 "2024-04-12T09:34:59Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [April 12, 2024, 9:53am UTC](https://discourse.julialang.org/t/what-is-the-design-and-proper-usage-of-functions-in-base-that-starts-with-underscore/112868/2 "2024-04-12T09:53:27Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [April 12, 2024, 11:03am UTC](https://discourse.julialang.org/t/what-is-the-design-and-proper-usage-of-functions-in-base-that-starts-with-underscore/112868/3 "2024-04-12T11:03:19Z")

</div>

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.
