# Dispatch and junk values

**URL:** <https://discourse.julialang.org/t/dispatch-and-junk-values/124497>\
**Category:** New to Julia\
**Tags:** dispatch\
**Created:** [January 7, 2025, 1:13pm UTC](https://discourse.julialang.org/t/dispatch-and-junk-values/124497 "2025-01-07T13:13:26Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![JADekker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jadekker/32/210281_2.png) [@JADekker](https://discourse.julialang.org/u/JADekker)\
**Post date:** [January 7, 2025, 1:13pm UTC](https://discourse.julialang.org/t/dispatch-and-junk-values/124497/1 "2025-01-07T13:13:26Z")

</div>

I have the following situation, where I have a function, where depending on the types of the supplied objects, I may or may not use all arguments. I then wish to define a shortcut function for some types of the supplied objects, which automatically fills the unused arguments by junk-values, so I can still make use of multiple dispatch.

I’ve made a slightly weird MWE, but I hope it clearly conveys what exactly I’m after. I’m also certain that this situation should perhaps typically be avoided, but in the specific situation I’m using, I think it is reasonable to do (at least for quick diagnostic purposes)

```julia
abstract type Foo end
struct Foo1 <: Foo end
struct Foo2 <: Foo end

abstract type Bar end
struct Bar1 <: Bar end
struct Bar2 <: Bar end

f(a::Foo1, b::Bar) = magic1(a, b) # Some function that crucially uses 'a' and 'b'
f(a::Foo2, b::Bar) = magic2(a) # Some function that only uses 'a', but which may be so complicated that it is easy to miss a typo, which means that 'b' is erroneously used
g(a::Foo2) = f(a, Bar1()) # If 'a' is of type 'Foo2', we know that 'f' won't use 'b', so we may supply any value here. 

```

Now I know that I will only be using the function `g` on objects of type `Foo2`, but as in my use-case the underlying types and functions are a bit complicated, I want to rule out that I make a mistake and `Bar1()` actually gets used.

I think my question is therefore: is there some way to tell Julia to pretend we’re using `f` with objects of type `Foo2` and `Bar` for the purpose of dispatching `f`, but you must not use the actual supplied value for `Bar` at any point? Something like `Junk(Bar)`, which creates an object with type `Bar` but that cannot be referenced?

---

<div class="post-metadata">

**Author:** ![JADekker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jadekker/32/210281_2.png) [@JADekker](https://discourse.julialang.org/u/JADekker)\
**Post date:** [January 7, 2025, 1:30pm UTC](https://discourse.julialang.org/t/dispatch-and-junk-values/124497/2 "2025-01-07T13:30:23Z")

</div>

I’m well aware that this can be achieved in some sense by defining

```julia
struct JunkBar <: Bar end

```

and using

```julia
g(a::Foo2) = f(a, JunkBar())

```

but this means I’ll (potentially) need to add a lot of such concrete types, which feels a bit wasteful.

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [January 7, 2025, 1:30pm UTC](https://discourse.julialang.org/t/dispatch-and-junk-values/124497/3 "2025-01-07T13:30:44Z")

</div>

You might want to restructure your computation to look something like this

```julia
# fallback
get_y(a::Foo, b::Bar) = a.y
# implement this for each concrete type <: Bar which has a field .y
get_y(a::Foo, b::Bar1) = b.y

f(a::Foo, b::Bar) = a.x + get_y(a, b)

```

---

<div class="post-metadata">

**Author:** ![JADekker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jadekker/32/210281_2.png) [@JADekker](https://discourse.julialang.org/u/JADekker)\
**Post date:** [January 7, 2025, 1:32pm UTC](https://discourse.julialang.org/t/dispatch-and-junk-values/124497/4 "2025-01-07T13:32:30Z")

</div>

For the specific MWE, that would be correct. In my case, the computations are however a bit harder and closer to:

```julia
f(a::Foo1, b::Bar1) = magic1(a, b)
f(a::Foo2, b::Bar) = magic2(a)

```

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [January 7, 2025, 1:35pm UTC](https://discourse.julialang.org/t/dispatch-and-junk-values/124497/5 "2025-01-07T13:35:24Z")

</div>

Why not use `y = get_y(a,b)` inside `magic1` and replace instances of `b.y` with `y` there?

* * *

I must admit I don’t understand the actual problem.  
`Bar1` is a concrete type which we know has a field `y`, so the solution is clear no?

---

<div class="post-metadata">

**Author:** ![JADekker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jadekker/32/210281_2.png) [@JADekker](https://discourse.julialang.org/u/JADekker)\
**Post date:** [January 7, 2025, 1:40pm UTC](https://discourse.julialang.org/t/dispatch-and-junk-values/124497/6 "2025-01-07T13:40:14Z")

</div>

I see that my original MWE may be a bit misleading, let me update it (I’ve also updated the OP):

```julia
abstract type Foo end
struct Foo1 <: Foo end
struct Foo2 <: Foo end

abstract type Bar end
struct Bar1 <: Bar end
struct Bar2 <: Bar end

f(a::Foo1, b::Bar) = magic1(a, b) # Some function that crucially uses 'a' and 'b'
f(a::Foo2, b::Bar) = magic2(a) # Some function that only uses 'a', but which may be so complicated that it is easy to miss a typo, which means that 'b' is erroneously used
g(a::Foo2) = f(a, Bar1()) # If 'a' is of type 'Foo2', we know that 'f' won't use 'b', so we may supply any value here. 

```

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [January 7, 2025, 1:50pm UTC](https://discourse.julialang.org/t/dispatch-and-junk-values/124497/7 "2025-01-07T13:50:08Z")

</div>

> [@JADekker](#):
>
> `f(a::Foo2, b::Bar) = magic2(a)`

I’m also lost but isn’t the fact that you don’t pass `b` to `magic2` enough to guarantee that `magic2` won’t use `b`?

But if you mean that `magic2(a)` rather is a shorthand for a direct implementation of a complicated function you can just skip naming the `Bar` argument:

```julia
function f(a::Foo2, ::Bar)
    # complicated stuff
end

```

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [January 7, 2025, 1:53pm UTC](https://discourse.julialang.org/t/dispatch-and-junk-values/124497/8 "2025-01-07T13:53:19Z")

</div>

I see. Some ideas:

- You can either use the `JunkBar <: Bar` like you already suggested.
- Alternatively declare `f` with `Union{Nothing,<:Bar}` and pass along `nothing` in `g`. If you have many types for which this is needed then you can declare a shorthand `const Maybe{T} = Union{Nothing,T}` and write it as `f(::Foo1, ::Maybe{<:Bar})` etc.
- Or just use the fact that `magic2` does not depend on `b` and separate dispatch and implementation by directly calling `magic2` instead of `f` from `g`.

However, I must say from my personal experience, its often simpler to just repeat some simple pattern and stick with it, in particular when using a more complicated solution only safes you about 5 min of changing your code, but is more difficult to reason about. Just my 2 cents.

---

<div class="post-metadata">

**Author:** ![JADekker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jadekker/32/210281_2.png) [@JADekker](https://discourse.julialang.org/u/JADekker)\
**Post date:** [January 7, 2025, 1:53pm UTC](https://discourse.julialang.org/t/dispatch-and-junk-values/124497/9 "2025-01-07T13:53:52Z")

</div>

Yes, `magic2(a)` is shorthand for a direct implementation of a complicated function. Not naming the `Bar` argument seems like a good way to ascertain this, that at least fixes my safety concerns.

However, I’d still need to pass some concrete instance of a subtype of `Bar` to use the function, right? I’d like to instead write something like `Junk(Bar)::Bar` and dispatch using that, if that is possible?

---

<div class="post-metadata">

**Author:** ![JADekker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jadekker/32/210281_2.png) [@JADekker](https://discourse.julialang.org/u/JADekker)\
**Post date:** [January 7, 2025, 1:57pm UTC](https://discourse.julialang.org/t/dispatch-and-junk-values/124497/10 "2025-01-07T13:57:06Z")

</div>

I see, thank you! I agree that the easy copy-paste solutions are usually fine for this kind of stuff, but it felt like a problem that might be sufficiently common to have its own solution.

I’m a bit wary of using the `Union` solution for legibility purposes, but I agree that sticking with `JunkBar` is probably sufficient!  
Thank you both for your suggestions!

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [January 7, 2025, 2:57pm UTC](https://discourse.julialang.org/t/dispatch-and-junk-values/124497/11 "2025-01-07T14:57:14Z")

</div>

> [@JADekker](#):
>
> I’d like to instead write something like `Junk(Bar)::Bar` and dispatch using that, if that is possible?

There is no mechanism in Julia to conjure up an unspecified instance of an abstract type but you can of course define an empty subtype yourself, as already noted, and use that:

```julia
abstract type Bar end
struct JunkBar <: Bar end
Junk(::Type{Bar}) = JunkBar()

```

If you truly have lots of such types so it becomes an annoying amount of boilerplate you could define a macro like

```julia
@junkable abstract type Bar end

```

which expands to the three lines above.
