# Outer constructor results in StackOverflowError

**URL:** <https://discourse.julialang.org/t/outer-constructor-results-in-stackoverflowerror/8246>\
**Category:** General Usage\
**Created:** [January 9, 2018, 3:15pm UTC](https://discourse.julialang.org/t/outer-constructor-results-in-stackoverflowerror/8246 "2018-01-09T15:15:06Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tpoisot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tpoisot/32/19812_2.png) [@tpoisot](https://discourse.julialang.org/u/tpoisot)\
**Post date:** [January 9, 2018, 3:15pm UTC](https://discourse.julialang.org/t/outer-constructor-results-in-stackoverflowerror/8246/1 "2018-01-09T15:15:06Z")

</div>

I’m trying to add an outer constructor for a parametric type, so that the object is only returned if it passes some tests. Here’s a MRE of what I’m trying to do:

```julia
abstract type MyAbstractType end

mutable struct MyType{ST,LT<:AbstractFloat} <: MyAbstractType
    a::Set{ST}
    b::Set{ST}
    c::Set{Tuple{ST,ST,LT}}
end

function MyType{ST,LT<:AbstractFloat}(a::Set{ST}, b::Set{ST}, c::Set{Tuple{ST,ST,LT}})
    if !all(0.0 .<= [x[3] for x in c] .<= 1.0)
        error("NOPE")
    end
    MyType(a, b, c)
end

i = Set([1, 2]) 
j = Set([3, 4])
k1 = Set([(1, 3, 0.2),(2, 4, 0.5)]) # Correct
k2 = Set([(1, 3, 0.2),(2, 4, 1.4)]) # Incorrect

MyType(i, j, k2) # Working - returns an error
MyType(i, j, k1) # Not working - StackOverflow

```

This results in a `StackOverflowError`, because the constructor calls itself (unless there is an error because the conditions are not satisfied).

I’m quite frankly lost about what is wrong with this code. Any tips?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [January 9, 2018, 3:18pm UTC](https://discourse.julialang.org/t/outer-constructor-results-in-stackoverflowerror/8246/2 "2018-01-09T15:18:42Z")

</div>

Use an inner constructor:

```julia
mutable struct MyType{ST,LT<:AbstractFloat} <: MyAbstractType
    a::Set{ST}
    b::Set{ST}
    c::Set{Tuple{ST,ST,LT}}
    function MyType{ST,LT<:AbstractFloat}(a::Set{ST}, b::Set{ST}, c::Set{Tuple{ST,ST,LT}})
        if !all(0.0 .<= [x[3] for x in c] .<= 1.0)
            error("NOPE")
        end
        new{ST, LT}(a, b, c)
    end
end

```

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [January 9, 2018, 3:19pm UTC](https://discourse.julialang.org/t/outer-constructor-results-in-stackoverflowerror/8246/3 "2018-01-09T15:19:13Z")

</div>

> [@tpoisot](#):
>
> MyType(a, b, c)

Instead do `MyType{eltype(a),...}(a, b, c)`

---

<div class="post-metadata">

**Author:** ![tpoisot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tpoisot/32/19812_2.png) [@tpoisot](https://discourse.julialang.org/u/tpoisot)\
**Post date:** [January 9, 2018, 3:28pm UTC](https://discourse.julialang.org/t/outer-constructor-results-in-stackoverflowerror/8246/5 "2018-01-09T15:28:26Z")

</div>

thanks!

---

<div class="post-metadata">

**Author:** ![favba](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/favba/32/2735_2.png) [@favba](https://discourse.julialang.org/u/favba)\
**Post date:** [January 9, 2018, 4:35pm UTC](https://discourse.julialang.org/t/outer-constructor-results-in-stackoverflowerror/8246/6 "2018-01-09T16:35:28Z")

</div>

If you want your struct to be created **only** if it pass the test you should use an inner constructor, as at-kristoffer.carlsson suggested. This way the test can never be by-passed. The outer constructor test can be by-passed if you call `MyType{eltype(a),...}(a,b,c)` directly.
