In short
julia> "Julia" == 0
false
but
julia> iszero("Julia")
ERROR: MethodError: no method matching zero(::String)
Closest candidates are:
zero(::Type{Base.LibGit2.GitHash}) at libgit2/oid.jl:106
zero(::Type{Base.Pkg.Resolve.VersionWeights.VWPreBuildItem}) at pkg/resolve/versionweight.jl:82
zero(::Type{Base.Pkg.Resolve.VersionWeights.VWPreBuild}) at pkg/resolve/versionweight.jl:124
...
Stacktrace:
[1] iszero(::String) at ./number.jl:22
But String
is relatively arbitrarily chosen here. An implication of this is that
julia> countnz([:Julia])
1
julia> countnz([[0.0]])
1
julia> !iszero([0.0])
false
because countnz
tests with x != 0
. It could also test with !iszero
but then countnz([:Julia])
would fail.
This came up in https://github.com/JuliaLang/julia/pull/22945 but is kind of separate from the PR so I think it deserves its own issue. There was a previous discussion of this issue in https://github.com/JuliaLang/julia/pull/17623#discussion_r92877227 but I'm not sure how many people noticed.
Possible solutions I can come up with are
iszero(x) = false
and use !iszero
whenever testing for zero in e.g. countnz
and find
. This would make countnz([[0.0]]) == 0
and countnz([:Julia]) == 1
==
method or make it try to convert the arguments to the same type and use !iszero
in countnz
and find
. This would make countnz([[0.0]]) == 0
and countnz([:julia])
fail, but probably also make a million other things throw.iszero
and ==
as they are but use !iszero
in countnz
and find
. This would make countnz([[0.0]]) == 0
and countnz([:julia])
fail.countnz([[0.0]]) == 1
(which I think is the wrong result) and countnz([:Julia]) == 1
Update: I think we should add this to the milestone for 1.0.
I've updated the top post with possible solutions
I guess the root of the problem is that x == 0
is ambiguous: it could be asking whether x
is very much like the object 0
, or it could be asking whether x
is the zero element of its group. For ==
I think we have no choice but to pick the first interpretation. So I guess I favor option (3): make all functions that explicitly name "zero" or "z" use the group-element interpretation, and leave ==
alone.
I think == 0
is a better fallback than false (maybe only tried when zero
is not applicable?) but otherwise 1 seems like the more desirable behavior to me - if there is no zero element, the answer is no, why error? I anticipate people would immediately start defining zero(::String)
in response to the error they would get here, and I don't think we should encourage that
Or perhaps iszero(x) = (x == zero(x))
? I'm fine with getting an error from countnz(["str"])
.
isn't that what it is now?
+1 to the idea of making countnz
call iszero
though.
I've only just started reading the issue, but the status quo actual seems best to me.
I think the iszero
usage can be easily written:
count(iszero, [1, 2, 3, 0])
Along the lines of what @vtjnash is proposing, I propose getting rid of the countnz
function entirely in favor of count(!iszero, A)
or whatever your favorite predicate is.
I think you mean count(!iszero, [1, 2, 3, 0])
, right?
Removing countnz
entirely is ok with me too. I like deleting stuff :)
Efficient implementation for sparse is roughly nnz(S)*pred(default) + count(p, S.values)
.
Fixed by #23485.
Most helpful comment
Removing
countnz
entirely is ok with me too. I like deleting stuff :)