# Symmetry in arguments and default behavior

**URL:** <https://discourse.julialang.org/t/symmetry-in-arguments-and-default-behavior/11924>\
**Category:** General Usage\
**Tags:** question\
**Created:** [June 25, 2018, 8:54am UTC](https://discourse.julialang.org/t/symmetry-in-arguments-and-default-behavior/11924 "2018-06-25T08:54:44Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![stakaz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stakaz/32/4740_2.png) [@stakaz](https://discourse.julialang.org/u/stakaz)\
**Post date:** [June 25, 2018, 8:54am UTC](https://discourse.julialang.org/t/symmetry-in-arguments-and-default-behavior/11924/1 "2018-06-25T08:54:44Z")

</div>

Hello, suppose I have the following types

```julia
abstract type Food end

struct Milk <: Food end
struct Berries <: Food end
struct Fish <: Food end 

```

Now, I want to introduce a function `mix` with 1) a default behavior for unknown subtypes of `Food` **and** with 2) symmetry in the arguments.

For the 1) I could write this:

```julia
mix(A::Food, B::Food) = "don't know how to mix"

```

for the 2) I can go with:

```julia
mix(A:.Food, B::Food) = mix(B, A)

```

But I can’t use both at the same time. When follow up with this code:

```julia
mix(A::Milk, B::Berries) = "milk shake"

```

I can run

```julia
mix(Milk(), Berries())
mix(Berries(), Milk())

```

but **not**

```julia
mix(Fish(), Milk())

```

which ends up in the following:

```julia
ERROR: LoadError: StackOverflowError:
Stacktrace:
 [1] mix(::Milk, ::Fish) at /media/DATA/PhD/code/ising/ising_julia_code/sandbox.jl:155 (repeats 80000 times)
while loading /media/DATA/PhD/code/ising/ising_julia_code/sandbox.jl, in expression starting on line 243

```

Is it possible to do it in a clever way **without** implementing

```julia
mix(A::Food, B::Something)

```

for each `Something <: Food` type separately?

Thanks

---

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [June 25, 2018, 9:02am UTC](https://discourse.julialang.org/t/symmetry-in-arguments-and-default-behavior/11924/2 "2018-06-25T09:02:28Z")

</div>

> [@stakaz](#):
>
> mix(A::Food, B::Food) = “don’t know how to mix”

I first thought was to use:

```
mix(A::Food, B::Food) = objectid(typeof(A)) ≤ objectid(typeof(B)) ? "don't know how to mix" : mix(B,A)

```

However, this fails as you would get a problem when `objectid(Berries) < objectid(Milk)` as then the arguments would not be reversed as expected.

---

<div class="post-metadata">

**Author:** ![stakaz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stakaz/32/4740_2.png) [@stakaz](https://discourse.julialang.org/u/stakaz)\
**Post date:** [June 25, 2018, 9:11am UTC](https://discourse.julialang.org/t/symmetry-in-arguments-and-default-behavior/11924/3 "2018-06-25T09:11:30Z")

</div>

> [@bkamins](#):
>
> objectid

Are you on julia 0.7? Because I don’t have this one?

However, the hash version works really nice.

---

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [June 25, 2018, 9:12am UTC](https://discourse.julialang.org/t/symmetry-in-arguments-and-default-behavior/11924/4 "2018-06-25T09:12:26Z")

</div>

Yes `objectid` is on Julia 0.7. I have withdrawn the post as I have to work a bit on it as it is not fully correct yet. I will post an update.

---

<div class="post-metadata">

**Author:** ![stakaz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stakaz/32/4740_2.png) [@stakaz](https://discourse.julialang.org/u/stakaz)\
**Post date:** [June 25, 2018, 9:14am UTC](https://discourse.julialang.org/t/symmetry-in-arguments-and-default-behavior/11924/5 "2018-06-25T09:14:01Z")

</div>

Ok, thanks for the quick reply anyway.

---

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [June 25, 2018, 9:30am UTC](https://discourse.julialang.org/t/symmetry-in-arguments-and-default-behavior/11924/6 "2018-06-25T09:30:47Z")

</div>

So this seems to be a possible way to do it:

```julia
function mix(A::Food, B::Food)
    if which(mix, (typeof(B), typeof(A))) === which(mix, (Food, Food))
        if which(mix, (typeof(A), typeof(B))) === which(mix, (Food, Food))
            "don't know how to mix"
        else
            mix(A, B)
        end
    else
        mix(B, A)
    end
end

```

The inner `if` is to safeguard against the following call:

```julia
invoke(mix, Tuple{Food, Food}, Milk(), Berries())

```

---

<div class="post-metadata">

**Author:** ![stakaz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stakaz/32/4740_2.png) [@stakaz](https://discourse.julialang.org/u/stakaz)\
**Post date:** [June 25, 2018, 9:34am UTC](https://discourse.julialang.org/t/symmetry-in-arguments-and-default-behavior/11924/7 "2018-06-25T09:34:14Z")

</div>

Could you please say, why using hashs or objectid was a bad way?

---

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [June 25, 2018, 9:45am UTC](https://discourse.julialang.org/t/symmetry-in-arguments-and-default-behavior/11924/8 "2018-06-25T09:45:26Z")

</div>

Reverted the answer above with information why it is wrong.
