Char == String?

just curious. what is the idea behind

julia> 'y' == "Y"
false

can a char string comparison ever be true? if not, would it make sense to designate this as an error? such a comparison is more indicative of an attempt of a=="Y" where a is char that holds ‘Y’ and more than likely a user programming bug.

The expression 'Y' == "Y" is handled by the default generic comparison method ==(x, y) at operators.jl:52
That method is defined as ==(x, y) = x === y.
I agree that this may surprise the unsuspecting user. Instead of flagging it as a bug, it may be better to meet expectations by defining

import Base: ==
==(x::Char,y::AbstractString) = length(y) == 1 && x == y[1]
==(x::AbstractString,y::Char) = y == x

No, that would be the equivalent of defining

==(x::Number, y::Vector) = length(y) == 1 && x == y[1]

which, I think you agree with, would be bad.

No, that would be extremely annoying. Consider a function like

foo(x) = contains(x, "Hello")

which would then error if a user called it like foo(Any['a', "Goodbye"]) although it clearly should return false – the vector does not contain "Hello".

3 Likes

Yes, that would be bad. But I don’t think your definitions is entirely equivalent. That is, it is technically equivalent, but the average user probably won’t see it that way. When they see 'Y'=="Y" they won’t see 'Y'==['Y'] but rather "Y"=="Y" or `‘Y’==‘Y’. The difference between a single quote and a double quote is just too subtle.

1 Like

could you please explain a little more what you mean? is this the function you mean?

julia> foo(x) = contains(x, "Hello")
foo (generic function with 1 method)

julia> foo(Any['a', "Goodbye"])
ERROR: MethodError: no method matching contains(::Array{Any,1}, ::String)
Closest candidates are:
  contains(::Function, ::Any, ::Any) at reduce.jl:664
  contains(::AbstractString, ::AbstractString) at strings/search.jl:378
Stacktrace:
 [1] foo(::Array{Any,1}) at ./REPL[59]:1
julia> Base.:(==)(c::Char, s::String) = error("Bad user")

julia> "Hello" in Any['c', "Goodbye"]
ERROR: Bad user
Stacktrace:
 [1] error at ./error.jl:33 [inlined]
 [2] == at ./REPL[13]:1 [inlined]
 [3] (::getfield(Base, Symbol("##180#181")){String})(::Char) at ./reduce.jl:737
 [4] hash_64_64 at ./int.jl:53 [inlined]
 [5] hash_uint64 at ./hashing.jl:62 [inlined]
 [6] hash at ./char.jl:196 [inlined]
 [7] hash at ./hashing.jl:18 [inlined]
 [8] hashindex at ./dict.jl:177 [inlined]
 [9] _any(::getfield(Base, Symbol("##180#181")){String}, ::Array{Any,1}, ::Colon) at ./dict.jl:316
 [10] #any#549 at ./reducedim.jl:637 [inlined]
 [11] any at ./reducedim.jl:637 [inlined]
 [12] in(::String, ::Array{Any,1}) at ./reduce.jl:737
 [13] top-level scope
1 Like

I understand the behaviour for == and in, but I am still confused by contains

julia> 'c' in Any['b', "Hello"]
false

julia> contains('c', "Hello")
ERROR: MethodError: no method matching contains(::Char, ::String)
Closest candidates are:
  contains(::Function, ::Any, ::Any) at reduce.jl:664
  contains(::AbstractString, ::AbstractString) at strings/search.jl:378

Woops, I should have looked more closely at the error…

julia> contains(==, 'c',"Hello")
false

contains was a bit of a confusing API, so it’s deprecated in 0.7. in is the correct function for the above demonstrative example.

1 Like