# Argument validation using Struct

**URL:** <https://discourse.julialang.org/t/argument-validation-using-struct/83397>\
**Category:** General Usage\
**Created:** [June 27, 2022, 12:03pm UTC](https://discourse.julialang.org/t/argument-validation-using-struct/83397 "2022-06-27T12:03:31Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![4mSwell](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/4mswell/32/37469_2.png) [@4mSwell](https://discourse.julialang.org/u/4mSwell)\
**Post date:** [June 27, 2022, 12:03pm UTC](https://discourse.julialang.org/t/argument-validation-using-struct/83397/1 "2022-06-27T12:03:31Z")

</div>

I am having trouble executing the code snippet below that was contributed on an old thread.

My objective is to define a struct that I can use to validate arguments inside function definitions. Any argument that is not the correct type should throw an error. The key point is that arguments are validated using types, not in the body of the function definition.

I realise I could validate the arguments in a separate “validation function”, which would be called in the body of each function definition. In my case this may provide a really neat, concise and readable solution as I have many functions with similar argument types.

```nohighlight
    value :: Int

    function OddInt(x :: Int)
        if isodd(x)
            return new(x)
        else
            throw(DomainError("$x is not odd"))
        end
    end
end

function thisoddball(n :: OddInt)
    return n
end

thisoddball(3)

```

The last call to thisodball(3) returns a method type error:  
Error: Methoderror: No method matching this oddball(::Int64)

As I understand it …thisoddball is testing to see that the argument n is of type OddInt. The structure OddInt however is returning a type Int64, and so the it produces a Method Error.

Calling OddInt(3) or OddInt(2) work just as expected.  
Calling a thisoddball(3) produces the method error described.

I should add that my situation has nothing to do with Odd numbers. This is just a self contained example that explains the issue as simply as possible.

---

<div class="post-metadata">

**Author:** ![4mSwell](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/4mswell/32/37469_2.png) [@4mSwell](https://discourse.julialang.org/u/4mSwell)\
**Post date:** [June 27, 2022, 12:07pm UTC](https://discourse.julialang.org/t/argument-validation-using-struct/83397/2 "2022-06-27T12:07:28Z")

</div>

Sorry the posted code snippet missed first line. I have reposted in full below.

```julia
struct OddInt
    value :: Int

    function OddInt(x :: Int)
        if isodd(x)
            return new(x)
        else
            throw(DomainError("$x is not odd"))
        end
    end
end

function thisoddball(n :: OddInt)
    return n
end

thisoddball(3)

```

---

<div class="post-metadata">

**Author:** ![mzaffalon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mzaffalon/32/214168_2.png) [@mzaffalon](https://discourse.julialang.org/u/mzaffalon)\
**Post date:** [June 27, 2022, 12:15pm UTC](https://discourse.julialang.org/t/argument-validation-using-struct/83397/3 "2022-06-27T12:15:44Z")

</div>

> The structure OddInt however is returning a type Int64, and so the it produces a Method Error.

The structure `OddInt` returns an object of type `OddInt`, not `Int64`.

Everything works as expected if you pass an `OddInt` object to the function `thisoddball`, because there in no method `thisoddball` defined for `Int`:

```julia
julia> thisoddball(OddInt(3))
OddInt(3)

```

The rest of your code can be shortened like this

```julia
struct OddInt
    value :: Int

    OddInt(x :: Int) =
        isodd(x) ? new(x) : throw(DomainError("$x is not odd"))
end

thisoddball(n :: OddInt) = n

```

---

<div class="post-metadata">

**Author:** ![4mSwell](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/4mswell/32/37469_2.png) [@4mSwell](https://discourse.julialang.org/u/4mSwell)\
**Post date:** [June 27, 2022, 1:08pm UTC](https://discourse.julialang.org/t/argument-validation-using-struct/83397/4 "2022-06-27T13:08:28Z")

</div>

Thanks, passing an OddInt object does indeed work.  
To help me understand … I was thinking that I could call “thisoddball(3)”. Not have to use “thisoddball(OddInt(3))”.

If I have the correct terminology, I thought that:

1. OddInt was an inner constructor for the structure OddInt??
2. (n :: OddInt) was a type assertion over the argument n?? In my head, that would call the OddInt constructor, and in the process it would execute any validation logic contained in that constructor (is n odd?). The “new” part of the constructor would then create the validated anonymous object??

Instead it feels like I am using a function (OddInt) as a parameter to another function “thisoddball”?

In a simpler scenario; for a function defined as `mydouble(x::Int) = x * 2`  
I would make the call ‘mydouble(2)’, not `mydouble(Int(2))'.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [June 27, 2022, 1:37pm UTC](https://discourse.julialang.org/t/argument-validation-using-struct/83397/5 "2022-06-27T13:37:17Z")

</div>

Dispatch does not work that way. If you define a method `foo(x::Bar)`, that means it will _only_ accept inputs of type `Bar` (or subtypes of `Bar` if it is an abstract type), it will not attempt to convert input to `Bar`.

When you define

```julia
thisoddball(n :: OddInt) = n

```

and you call `thisoddball(3)`, the compiler gets the type of the input, which is `Int64`, and checks if there is a method `thisoddball(::Int)`. There is not such method, so you get an error.

What you can do instead if this:

```julia
thisoddball(n::OddInt) = n
thisoddball(n::Int) = thisoddball(OddInt(n))

```

As for this:

> [@4mSwell](#):
>
> In a simpler scenario; for a function defined as `mydouble(x::Int) = x * 2`  
> I would make the call ‘mydouble(2)’, not `mydouble(Int(2))'.

`2` is already of type `Int` so `mydouble(2)` should work, while `mydouble(2.0)` or `mydouble(0x2)` should not.

---

<div class="post-metadata">

**Author:** ![mzaffalon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mzaffalon/32/214168_2.png) [@mzaffalon](https://discourse.julialang.org/u/mzaffalon)\
**Post date:** [June 27, 2022, 1:41pm UTC](https://discourse.julialang.org/t/argument-validation-using-struct/83397/6 "2022-06-27T13:41:24Z")

</div>

In case you want to use `thisoddball(3)` you have to define it: `thisoddball(n::Int) = OddInt(n)`.

1. correct: `OddInt` is in the inner constructor;
2. wrong: you should read `(n :: OddInt)` as part of the definition of `thisoddball(n :: OddInt)`. There is only one function that only takes `OddInt`.

---

<div class="post-metadata">

**Author:** ![4mSwell](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/4mswell/32/37469_2.png) [@4mSwell](https://discourse.julialang.org/u/4mSwell)\
**Post date:** [June 27, 2022, 2:58pm UTC](https://discourse.julialang.org/t/argument-validation-using-struct/83397/7 "2022-06-27T14:58:54Z")

</div>

Thank you both (DNF & mzaffalon) for thoughtful, concise responses. Both answers help me to better understand topics I have grappled with. Hopefully it may also help others.

DNF: (and similar answer from mzafflon) - where you propose what I could do instead… I think of this as multiple dispatch. In my head, you are defining two methods for thisoddball. One method with an OddInt Object argument type, the second with an Int argument type.

Other parts of your answers also resonated with me. (Not how dispatch works, doesn’t attempt to convert input, part of the definition of thisoddball…)

Thanks again.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [June 27, 2022, 3:08pm UTC](https://discourse.julialang.org/t/argument-validation-using-struct/83397/8 "2022-06-27T15:08:07Z")

</div>

> [@4mSwell](#):
>
> One method with an OddInt Object argument type, the second with an Int argument type.

Yes, exactly. This is a very common pattern in Julia code.
