Base.div vs Html.div - specialize or not?

Save us from what?

This is essentially a question of style — for generic programming, ideally all methods of a function do something similar. But there is nothing in the language enforcing this, and for your own types it is not even type piracy. So one can do

struct WackyType end
Base.div(::WackyType) = :wack

pretty much without any major adverse consequences; it is just poor style.

Minor consequences include confusing users using methods, documentation, and similar.

1 Like

One additional option would be to turn all of the tags into string macros instead of functions:

div"hello world"(; class="shadowbox")

EDIT: nevermind. This doesn’t work for nested elements. Unless you instead had the contents of the string macro be irrelevant:

div""("hello world")
julia> methods(div) # I see my added test div buried in the middle...:
# 59 methods for generic function "div":

[29] div(s::AbstractString) in Main at none:1

[32] div(x::Bool, y::Bool) in Base at bool.jl:110

I wouldn’t worry about beginners looking at methods, I would at least worry more about div not being available, in the simplest form for HTML (I note, it’s rare to use div for division, and ÷ preferred by me, if not / or other operator, most users would).

This is more confusing:

julia> div(false, false)
ERROR: DivideError: integer division error
Stacktrace:
 [1] div(x::Bool, y::Bool)
   @ Base ./bool.jl:110
 [2] top-level scope
   @ none:1

julia> div(false, true)
false

If this is only about style and actually always working, I’m ok with impurity, want to make sure I’m not overlooking something (invalidations? making code loading slower?), e.g. could something like this be an issue:

[9] div(a::DataValues.DataValue{T1}, b::T2) where {T1, T2} in DataValues at /home/pharaldsson_sym/.julia/packages/DataValues/N7oeL/src/scalar/operations.jl:65

[13] div(::Number, ::Missing, r::RoundingMode) in Base at missing.jl:122

This is just division by 0, what does this have to do with the topic we are discussing? :man_shrugging:

2 Likes

I did participate in this thread, where I was opposed to your opinion. I was a bit more in agreement with Jeff Bezanson. I actually wrote some software in reaction to this thread, see
Using_merge.jl

Aye, but that requires using a HtmlString or some other type that is defined in the package and the whole purpose is to decrease boilerplate so that would probably defeat the purpose.

For example, stderr in I/O context is one thing but in statistics is another. Would having it do two very different things sharing the name, why not? It is not context ambiguous. The issue is avoiding type piracy. Other than that, just make sure that the new methods have a clear docstring to avoid confusion.

Yes, stderr is a good example of a term which has different meaning in different contexts, which is
in my view the exact case were kristoffer’s assertion is needlessly limiting what Julia can do.

Another example where I “pirated” Base in my package is that in mathematics, conjugacy in a non-commutative group (that is, the conjugate of g by h is inv(h)*g*h) is denoted like exponentiation
by a superscript g^h. It is thus natural to define

Base.:^(g::GroupElement,h::GroupElement)=inv(h)*g*h

An example of conjugacy in a non-commutative group is conjugacy of matrices, and I regret that
there is no notation for it in Julia (as far as I know).

Maybe I am missing some context, but if GroupElement is a type your package owns, the above code is not type piracy.

Yes, in my view it is not piracy. But I guess it is in Kristoffer’s view which is why I used the term.
And I hope that in your view it is not poor style either…

Kristoffer never said it was piracy, he said it was a bad idea because it makes it hard to know what generic code does. The term I hear people use for this is ‘pun’.

Piracy is a bad idea because it breaks code, or at least makes it harder to not break code.

5 Likes