I recently wrote something like the following:
val char:Char = foo(bar)
if char == 'x' or char =="y":
println("branch 1")
else:
println("branch 2")
And couldn't figure out why branch 1 was not executing when char
was 'y'
. The issue is that y
is in double quotes in the comparison, making it a String
rather than a Char
, so the comparison was always false
. As far as I understand, the problem stems from the fact that equal?
is defined as:
public defmulti equal? (a:Equalable, b:Equalable) -> True|False
Which means that the compiler has no way of noticing the mistake, because Char
and String
are both Equalable
. However, we could introduce:
defn same-type-equal?<?T> (a:?T & Equalable, b:T & Equalable) -> True|False:
a == b
Then compiling same-type-equal?('y', "y")
gives the following error:
Cannot call function same-type-equal? of type (Equalable&Char, Equalable&Char) -> True|False
with arguments of type (Char, String).
While same-type-equal?('y', 'y')
compiles without error.
I see a few ways to solve this issue:
- Create an
===
operator that would use same-type-equal? (And analogous !==
operator), so that 'x' === "x"
does not compile. I like this option.
- Add a method to the
equal?
multi for comparing Char
values to String
values.
- Do nothing, developers should know to not write
'x' == "x"
.
- Change
equal?
to same-type-equal?
. From what I can tell, this goes against the design philosophy of the language, because users would no longer be able to write methods for equal?
that take two different types, even if it makes sense in some cases.
I am interested in hearing other people's opinions on this issue, whether they think it should be solved, and if so, the best way to do so.