# What new() in inner costructor do?

**URL:** https://discourse.julialang.org/t/what-new-in-inner-costructor-do/133251
**Category:** New to Julia
**Tags:** question, documentation, education
**Created:** [October 17, 2025, 10:55pm UTC](https://discourse.julialang.org/t/what-new-in-inner-costructor-do/133251 "2025-10-17T22:55:47Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![raman\_kumar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raman_kumar/32/26782_2.png) [@raman\_kumar](https://discourse.julialang.org/u/raman_kumar)
#### Post date: [October 17, 2025, 10:55pm UTC](https://discourse.julialang.org/t/what-new-in-inner-costructor-do/133251/1 "2025-10-17T22:55:47Z")

</div>

- What does [new](https://docs.julialang.org/en/v1/base/base/#new) in general do in inner constructor? For example in this code in documentation how `new` know the work( _here create instance if x\>y_) it should do? [Constructors · The Julia Language](https://docs.julialang.org/en/v1/manual/constructors/#man-inner-constructor-methods)

```julia-auto

julia> struct OrderedPair
           x::Real
           y::Real
           OrderedPair(x,y) = x > y ? error("out of order") : new(x,y)
       end

```

- What are the advantages of using **inner constructor**?

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [October 17, 2025, 11:38pm UTC](https://discourse.julialang.org/t/what-new-in-inner-costructor-do/133251/2 "2025-10-17T23:38:05Z")

</div>

Pretty much exactly what the docs say:

> 1. [An inner constructor method] has access to a special locally existent function called [`new`](https://docs.julialang.org/en/v1/base/base/#new) that creates objects of the block’s type.

The fields you write in the `struct` definition is all `new` needs to instantiate the object. `new` instantiation is only available inside the struct definition so it can specially lowered for the type; outside, it can only be treated as another global name.

Outer constructor methods must call inner constructor methods but can be written from other modules. So, implement inner constructor methods for the basics then outer constructors on different input types for flexibility.

---

<div class="post-metadata">

### Author: ![Salmon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/salmon/32/22968_2.png) [@Salmon](https://discourse.julialang.org/u/Salmon)
#### Post date: [October 18, 2025, 5:01pm UTC](https://discourse.julialang.org/t/what-new-in-inner-costructor-do/133251/3 "2025-10-18T17:01:15Z")

</div>

> [@raman\_kumar](#):
>
> What are the advantages of using **inner constructor**?

To answer the second question: you often do not actually need an inner constructor. The major reason to have an inner constructer is that you can ensure that certain constraints are fulfilled, even if another outer constructor is added later.  
I.e. in your example it is now impossible to create any OrderedPair that is not ordered.

---

<div class="post-metadata">

### Author: ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)
#### Post date: [October 18, 2025, 7:50pm UTC](https://discourse.julialang.org/t/what-new-in-inner-costructor-do/133251/4 "2025-10-18T19:50:44Z")

</div>

> [@raman\_kumar](#):
>
> What are the advantages of using **inner constructor**?

1. Ensure some invariants on constructed objects.  
That’s the most typical case and is demonstrated in the docs.
2. Create partially-initialized mutable structs (see [Constructors · The Julia Language](https://docs.julialang.org/en/v1/manual/constructors/#Incomplete-Initialization)). That’s a rare need, but still.

Typically, I recommend starting with the default constructors when writing your own code. Case (2) is very specific, and if you are wondering why you need it then you probably don’t.  
Case (1) is arguably not needed if the actual arguments passed to the default constructor never violate the invariants. In practice, if you code for yourself or for a small collective, that’ll likely to be true. Basically, you only need those safeguards if you decide to make your code available to a large audience.

---

<div class="post-metadata">

### Author: ![raman\_kumar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raman_kumar/32/26782_2.png) [@raman\_kumar](https://discourse.julialang.org/u/raman_kumar)
#### Post date: [October 18, 2025, 8:15pm UTC](https://discourse.julialang.org/t/what-new-in-inner-costructor-do/133251/5 "2025-10-18T20:15:18Z")

</div>

> [@Vasily\_Pisarev](#):
>
> Ensure some invariants on constructed objects.

What are [**invariants**](https://docs.julialang.org/en/v1/devdocs/llvm/#Invariants) in Julia terminology? Are they same as _constant_ that do not varies?

---

<div class="post-metadata">

### Author: ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)
#### Post date: [October 18, 2025, 9:38pm UTC](https://discourse.julialang.org/t/what-new-in-inner-costructor-do/133251/6 "2025-10-18T21:38:14Z")

</div>

Invariant is some property that must hold true for a program to be correct. That’s not Julia terminology, that’s a general CS term ([Invariant (mathematics) - Wikipedia](https://en.wikipedia.org/wiki/Invariant_(mathematics)#Invariants_in_computer_science)).  
For types, it’s some property that must be true for all objects of a given type.

A semi-realistic example where one faces actual design choices, each with its own pros and cons.

Let’s say we design a type for a QR decomposition and we want to store Q and R matrices explicitly:

```julia-auto
struct QRDecomposition
    Q::Matrix{Float64}
    R::Matrix{Float64}
end

```

Now, Q must be an orthogonal matrix, i.e. Q^TQ = I, R must be upper-triangular and the sizes of the matrices must be compatible. How do we guarantee that?

1. We write an inner constructor `QRDecomposition(Q, R)` where we check those properties – orthogonality check in particular is quite expensive due to matrix product, so that the constructor will incur some unavoidable overhead.
2. We only allow the construction of the object by performing an actual QR decomposition of some matrix: the only inner constructor will be `QRDecomposition(M)` will perform the decomposition of matrix M. A plausible solution, but then we tie the users to a hardcoded decomposition algorithm.
3. We just keep the default constructor `QRDecomposition(Q, R)` but declare it an implementation detail. The public interface will be using a function `qr(M)`. That way, we don’t guarantee the consistency of `QRDecomposition` objects in general, only of those returned by the function `qr`. On the other hand, users can now construct such objects from pre-computed decompositions without invariant-checking overhead. Also, users can easily add their own functions to optimize QR decomposition for special types of matrices if they have such needs.

In practice, option (3) is quite common: the type constructor is not supposed to be used directly; the most common case is covered by a helper function; advanced users can play with the low-level interface at their own risk.
