# Method that acts on union types, what is wrong?

**URL:** <https://discourse.julialang.org/t/method-that-acts-on-union-types-what-is-wrong/49057>\
**Category:** New to Julia\
**Created:** [October 26, 2020, 4:39pm UTC](https://discourse.julialang.org/t/method-that-acts-on-union-types-what-is-wrong/49057 "2020-10-26T16:39:22Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 26, 2020, 4:39pm UTC](https://discourse.julialang.org/t/method-that-acts-on-union-types-what-is-wrong/49057/1 "2020-10-26T16:39:22Z")

</div>

What is wrong with this definition of a method that is thought to work on both types defined?

```julia
julia> struct A end

julia> struct B end

julia> function test( x :: T, y :: T ) where T <: Union{A,B}
         true
       end
test (generic function with 1 method)

julia> a = A() ; b = B();

julia> test(a,b)
ERROR: MethodError: no method matching test(::A, ::B)
Closest candidates are:
  test(::T, ::T) where T<:Union{A, B} at REPL[84]:1
Stacktrace:
 [1] top-level scope at REPL[86]:1

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 26, 2020, 4:44pm UTC](https://discourse.julialang.org/t/method-that-acts-on-union-types-what-is-wrong/49057/2 "2020-10-26T16:44:54Z")

</div>

Ok, it is expecting that the type is the same for both variables. This works:

```julia
julia> function test( x :: T1, y :: T2 ) where {T1 <: Union{A,B}, T2 <: Union{A,B}}
         true
       end
test (generic function with 3 methods)

julia> test(a,b)
true

```

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [October 26, 2020, 4:50pm UTC](https://discourse.julialang.org/t/method-that-acts-on-union-types-what-is-wrong/49057/3 "2020-10-26T16:50:21Z")

</div>

If you don’t need the type parameter inside the function body, then you could just write that as this:

```julia
julia> function test(x::Union{A,B}, y::Union{A,B})
           true
       end
test (generic function with 1 method)

julia> test(a, b)
true

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 26, 2020, 4:55pm UTC](https://discourse.julialang.org/t/method-that-acts-on-union-types-what-is-wrong/49057/4 "2020-10-26T16:55:12Z")

</div>

No, I do not need it. But in my case we are talking of

```julia
Union{ComplexMixtures.Result,ComplexMixtures.Density,ComplexMixtures.Volume}

```

writing this more than once is not fun. I guess nothing is wrong on using `:: T`, wright?

By the way, I am just writing an `isapprox` function that compares every field of a struct. Is there already a base function for that?

```julia
function isapprox( r1 :: T, r2 :: T ) where T <: Union{ComplexMixtures.Result,ComplexMixtures.Density,ComplexMixtures.Volume}
  check = true
  for field in fieldnames(typeof(r1))
    x = getfield(r1,field)
    y = getfield(r2,field)
    if ! (x ≈ y)
      check = false
      println(" Data in $field field differ. ")
    end
  end
  return check
end

```

Edit: Rs, I just realized that I do need the type 🙂, I was just using `typeof` instead 😬

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [October 26, 2020, 5:11pm UTC](https://discourse.julialang.org/t/method-that-acts-on-union-types-what-is-wrong/49057/5 "2020-10-26T17:11:16Z")

</div>

> [@lmiq](#):
>
> ```julia
> Union{ComplexMixtures.Result,ComplexMixtures.Density,ComplexMixtures.Volume}
> 
> ```
> 
> writing this more than once is not fun.

why not define in your module:

```julia
const AMixture = Union{ComplexMixtures.Result,ComplexMixtures. ...}

```

Then you can use `AMixture` in your definitions and Julia expands it to the longer term.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 26, 2020, 5:12pm UTC](https://discourse.julialang.org/t/method-that-acts-on-union-types-what-is-wrong/49057/6 "2020-10-26T17:12:59Z")

</div>

Yes, sure. Yet for the moment I only need that Union in exactly that point. That test function is the only requiring this type of input.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [October 26, 2020, 5:34pm UTC](https://discourse.julialang.org/t/method-that-acts-on-union-types-what-is-wrong/49057/7 "2020-10-26T17:34:07Z")

</div>

> [@lmiq](#):
>
> Edit: Rs, I just realized that I do need the type 🙂, I was just using `typeof` instead 😬

If you haven’t overloaded `getproperty`, you could use `propertynames`, which accepts an instance rather than a type:

```julia
propertynames(r1)

```

Also, do you need to do an intersection of the field/property names for `r1` and `r2`?

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [October 26, 2020, 5:41pm UTC](https://discourse.julialang.org/t/method-that-acts-on-union-types-what-is-wrong/49057/8 "2020-10-26T17:41:41Z")

</div>

> [@lmiq](#):
>
> I was just using `typeof` instead

By the way, that’s _completely fine_ if it makes your code easier to write or read or maintain. You are free to write:

```julia
function foo(x)
  println("the type of x is: ", typeof(x))
end

```

instead of

```julia
function foo(x::T) where {T}
  println("the type of x is: ", T)
end

```

and you should expect to see little or no difference in the performance of your code (in fact, I suspect the compiler will generate exactly the same code in most cases). After all, if the compiler has access to the type of `x`, then it can insert the answer to `typeof(x)` without requiring any work to be done at runtime.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 26, 2020, 5:55pm UTC](https://discourse.julialang.org/t/method-that-acts-on-union-types-what-is-wrong/49057/9 "2020-10-26T17:55:08Z")

</div>

> [@CameronBieganek](#):
>
> `propertynames(r1)`

Oh, cool, I didn’t know about that.

> [@CameronBieganek](#):
>
> Also, do you need to do an intersection of the field/property names for `r1` and `r2` ?

I am not sure if I understand the question. I am actually comparing two instances of the same structs, and I want to be sure that all the data contained in them is the same (the result of a test case computation of the package). These structs contain other structs inside (of those 4 types of my program), such that that `isapprox` function runs for all the fields of everything.

Ah, I think now I understand your question: no, no, the fields are the same. If the structs where different of course that loop would have to be on the common fields of both structures only.

The original question was, actually, a result of me not knowing how the parametric type worked, because I was adding manually an error message to stop the execution if the two types were different. Thus, what I actually wanted was ` ( x :: T, y :: T ) where T <: Union{A,B}`, which will throw an error if the types are different.
