Hi all,
I often see the word “maybe” in function names especially in ModelingToolkit.
for example “maybe_build_initialization_problem()” or “MaybeArrayIndexT”
Is this a common convention in Julia? What does it mean?
Hi all,
I often see the word “maybe” in function names especially in ModelingToolkit.
for example “maybe_build_initialization_problem()” or “MaybeArrayIndexT”
Is this a common convention in Julia? What does it mean?
I am not aware there is a common understanding or fixed use.
Until now I have seen it in the sense of ensuring something. For your function maybe_build_X() is probably means “build X if it was not build yet – or check whether it needs to be build at all”. Maybe more precise would be something with “enusre” (that it is build if needed)
For types I indeed have not yet seen it yet. I personally prefer to have types precise.
I agree, I don’t think that it has a standard meaning across packages or ecosystems.
Where I have seen it used for types is e.g. in Configurations.jl where Maybe{T} is just an alias for Union{T, Nothing}. I think it makes sense here since the goal is to write “configuration structs” (or parameter structs) where you might have fields that can have a value of type T, but there is no meaningful default value, so nothing can be used instead (to turn off some functionality altogether for instance).
Another example (kind of) are DataFrames from DataFrames.jl. The element type of a column is sometimes inferred to be Union{T, Missing} if not all rows contain an element (when printing, this shows up as T? which I find pretty clever), but it might as well be named Maybe{T} because when you read elements from that column, you maybe get an actual T or … something else (but it’s not called that).
But it’s very context-specific and, as @kellertuer mentioned, types usually benefit from being concrete. But a Maybe{T} will probably perform better than Any.
This meaning for types (either T or some placeholder type) is also found in other languages as far as I recall (Rust?).
I haven’t discerned a strong convention around the (handful of) maybeX functions I’ve seen. But sometimes I’ll write my own to perform certain operations. Especially to add to or modify functionality of existing functions without piracy.
For example, one function I’ve written is this (it could be written better – for example to evaluate the entries of p individually – but this was sufficient for my needs):
using LinearAlgebra # for UniformScaling
maybematrixpoly(x, p) = evalpoly(x, p)
function maybematrixpoly(x::Union{AbstractMatrix, UniformScaling}, p)
if eltype(p) <: Number # scalar coefficients
return evalpoly(x, UniformScaling.(p))
else
return evalpoly(x, p)
end
end
The intent is to be the same as evalpoly, but to work on both numbers and (square) matrices. evalpoly on its own did not work because it cannot apply scalar polynomial coefficients to a matrix (because it would attempt to add a number to a matrix). So for the case of matrix polynomials with scalar coefficients, it promotes the coefficients to UniformScaling (scaled identity matrices).
Here’s (my recollection of) another function I’ve used before. I had code where I wanted to copy a generic object that I didn’t know much about in advance. The issue is that most immutables don’t have a copy method so I couldn’t just call copy on them. I can’t find the original any more but it looked something like this:
maybecopy(x) = copy(x)
# add exceptions as necessary
maybecopy(x::String) = x # not copyable and copy not necessary
maybecopy(x::Symbol) = x # not copyable and copy not necessary
maybecopy(x::Nothing) = x # not copyable and copy not necessary
# maybecopy(x::Tuple) = maybecopy.(x) # if you want Tuple fields handled recursively
# maybecopy(x::Tuple) = x # if you want Tuples not copied
If I ran into a type that couldn’t copy, I would add a method here with the behavior I wanted. I won’t strongly advocate for this one in particular, however, as it might be code smell to need this (hard to find a consolidated place with full discussion, but see some at #57219). Still, it’s much better to do something like this than pirate the original function.
One maybe-flavored function (though without the name) in Base is get.
Base has an internal mightalias too