# Redefining == operator doesn't behave expectedly

**URL:** https://discourse.julialang.org/t/redefining-operator-doesnt-behave-expectedly/108303
**Category:** New to Julia
**Tags:** question
**Created:** [January 3, 2024, 1:14pm UTC](https://discourse.julialang.org/t/redefining-operator-doesnt-behave-expectedly/108303 "2024-01-03T13:14:16Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Joslacrosse](https://avatars.discourse-cdn.com/v4/letter/j/35a633/32.png) [@Joslacrosse](https://discourse.julialang.org/u/Joslacrosse)
#### Post date: [January 3, 2024, 1:14pm UTC](https://discourse.julialang.org/t/redefining-operator-doesnt-behave-expectedly/108303/1 "2024-01-03T13:14:16Z")

</div>

I have a problem with a coding execise from Exercism, i habe been trying to solve it for some hours now

I think the problem lies with the connectd == and != as if i tests the statements individually they work out.  
Does anyone know how to redefine the == so that the test will go through

The code doesnt clear one of the tests:

````julia
function toIntArray(ISBN::String)
    dig ="0123456789"
    isbn=[]
    for i in 1:length(ISBN)
        if in(ISBN[i],dig)
            append!(isbn,Int(ISBN[i]-48))
            elseif ISBN[i]=='X' && (i-length(ISBN))==0
            append!(isbn,10)
            elseif ISBN[i] =='-'
            else
                throw(DomainError("Snake on the plane"))
        end
    end
    return(isbn)
end

struct ISBN
    isbn::Array{Int}

    function ISBN(ISBN::String)
        storage=0
        isbn = toIntArray(ISBN)
        if length(isbn)!= 10
            throw(DomainError("tooloongortooshoort"))
        end

        for i in 1:length(isbn)
            storage=storage+ isbn[i]*(11-i)
        end
        if storage %11 ==0 
            return(true) 
        else 
            throw(DomainError("Thats the wrong number"))
        end
    end
end

function Base.:(==)(i1::ISBN, i2::ISBN)
    return toIntArray(i1)==toIntArray(i2)
end
function Base.:(!=)(i1::ISBN, i2::ISBN)
    return toIntArray(i1)!=toIntArray(i2)
end 
´´´ 
The test is 
´´´ ISBN("3-598-21508-8") == ISBN("3598215088") != ISBN("3-598-21507-X") ```
(should result in true but results in false)

the ecercise can be found at https://exercism.org/tracks/julia/exercises/isbn-verifier
````

---

<div class="post-metadata">

### Author: ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)
#### Post date: [January 3, 2024, 1:48pm UTC](https://discourse.julialang.org/t/redefining-operator-doesnt-behave-expectedly/108303/2 "2024-01-03T13:48:29Z")

</div>

Welcome to the forum! 🙂

I don’t want to solve the exercise for you so I will just give you some hints:

1. You should check what `ISBN("3-598-21508-8")` returns. It is not of type `ISBN` because your constructor (the `ISBN` function inside the struct’s definition) never calls `new` to actually construct an instance. Have a look at [the manual’s section on constructors](https://docs.julialang.org/en/v1/manual/constructors/#man-inner-constructor-methods)
2. Once you fix that, you will notice that your definitions of `==` and `!=` don’t make sense as you didn’t define a method for `toIntArray` that takes `ISBN` types. So you’ll probably want to rethink what these methods should do.

Come back if you need more hints!

Edit: When you solved it, you can also post your solution and I will give you some pointers how to make it more idiomatic and point out some beginner mistakes i.e. concerning the typing of variables 🙂

---

<div class="post-metadata">

### Author: ![Joslacrosse](https://avatars.discourse-cdn.com/v4/letter/j/35a633/32.png) [@Joslacrosse](https://discourse.julialang.org/u/Joslacrosse)
#### Post date: [January 3, 2024, 3:15pm UTC](https://discourse.julialang.org/t/redefining-operator-doesnt-behave-expectedly/108303/3 "2024-01-03T15:15:44Z")

</div>

Hey abraemer,

Great advice  
i have succceeded to resolve the problem with your help i think its not the most elegant solution but it works  
I changes the constructor from returning the ISBN to new(isbn) # I think that leads to a new instance being created ?  
I overloaded the toIntArray function to facilitate it to turn instances of isbn into an IntArray

Thank you very much vor your help! 😀

Here is the current code that manages to pass all the tests:

```julia
struct ISBN
    isbn::Array{Int}

    function ISBN(ISBN::String)
        storage=0
        isbn = toIntArray(ISBN)
        if length(isbn)!= 10
            throw(DomainError("tooloongortooshoort"))
        end

        for i in 1:length(isbn)
            storage=storage+ isbn[i]*(11-i)
        end
        if storage %11 ==0 
            new(isbn) 
        else 
            throw(DomainError("Thats the wrong number"))
        end
    end
end

function toIntArray(ISBN::String)
    dig ="0123456789"
    isbn=[]
    for i in 1:length(ISBN)
        if in(ISBN[i],dig)
            append!(isbn,Int(ISBN[i]-48))
            elseif ISBN[i]=='X' && (i-length(ISBN))==0
            append!(isbn,10)
            elseif ISBN[i] =='-'
            else
                throw(DomainError("Snake on the plane"))
        end
    end
    return(isbn)
end

function toIntArray(isbn::ISBN)
    dig ="0123456789"
    result=[]
    for i in 1:10
        append!(result, Int(isbn.isbn[i]))
    end
    return(result)
end

function Base.:(==)(i1::ISBN, i2::ISBN)
    return toIntArray(i1)==toIntArray(i2)
end

```

---

<div class="post-metadata">

### Author: ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)
#### Post date: [January 3, 2024, 4:21pm UTC](https://discourse.julialang.org/t/redefining-operator-doesnt-behave-expectedly/108303/4 "2024-01-03T16:21:19Z")

</div>

Glad my hints where helpful 🙂

As promised some comments:

- General logic: your ISBN struct stores the digits of the ISBN, so when you want to compare to instances, you could just compare their arrays directly. Your function `toIntArray(isbn::ISBN)` really just performs a slow copy of the stored array. So you can just do:

```julia
Base.:(==)(i1::ISBN, i2::ISBN) = i1.isbn == i2.isbn

```

- Typing: You annotated the field `isbn` in your `ISBN` struct with `Array{Int}` which is not a good annotation because `Array` denotes a multi-dimensional array and its full type signature carrys the dimension as well. So it would be better (for performance) to write the type as `Array{Int, 1}` or just `Vector{Int}` which means the same thing. However you could also just leave the type out if you don’t care about performance. Julia does not require you to give fields a type.
- You could shorten the `toIntArray` function a bit using Julia’s `isdigit` function and a bit of [broadcasting magic (see manual)](https://docs.julialang.org/en/v1/manual/arrays/#Broadcasting):

```julia
function toIntArray(ISBN::String)
    digits_string = filter(isdigit, ISBN)
    digits = parse.(Int, collect(digits_string)) # note that strings are scalars for broadcasting, so I use collect to turn it into a Vector{Char}
    if ISBN[end] == 'X'
        push!(digits, 10)
    end
    return digits
end

```

- you could consider making the verification of an ISBN its own function. That way you could use that functionality elsewhere and it also would clear up the constructor a bit.

---

<div class="post-metadata">

### Author: ![Joslacrosse](https://avatars.discourse-cdn.com/v4/letter/j/35a633/32.png) [@Joslacrosse](https://discourse.julialang.org/u/Joslacrosse)
#### Post date: [January 4, 2024, 7:18am UTC](https://discourse.julialang.org/t/redefining-operator-doesnt-behave-expectedly/108303/5 "2024-01-04T07:18:55Z")

</div>

Thanks for the great feedback! I‘ll try to implement it! 😀
