# Use function argument inside optional (default) arguments type specification

**URL:** https://discourse.julialang.org/t/use-function-argument-inside-optional-default-arguments-type-specification/70963
**Category:** General Usage
**Tags:** question, type, function
**Created:** [November 4, 2021, 4:18pm UTC](https://discourse.julialang.org/t/use-function-argument-inside-optional-default-arguments-type-specification/70963 "2021-11-04T16:18:36Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![claudio20497](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/claudio20497/32/36602_2.png) [@claudio20497](https://discourse.julialang.org/u/claudio20497)
#### Post date: [November 4, 2021, 4:18pm UTC](https://discourse.julialang.org/t/use-function-argument-inside-optional-default-arguments-type-specification/70963/1 "2021-11-04T16:18:37Z")

</div>

Hi,

I encountered the following behaviour. I can use a function’s arguments to set the default values for optional (default) arguments:

```julia
julia> f(a::Int64; b::Int64 = a-1 ) = b
f (generic function with 1 method)

```

But I can’t use the same argument to specify the type of optional (default) arguments:

```julia
julia> g(a::Int64; b::NTuple{a, Int64} = Tuple(repeat([a], a))) = b
ERROR: UndefVarError: a not defined
Stacktrace:
 [1] top-level scope
   @ REPL[3]:1

```

Why is this? Is there any way to specify the optional (default) argument types of a function using the function’s arguments?

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [November 4, 2021, 4:32pm UTC](https://discourse.julialang.org/t/use-function-argument-inside-optional-default-arguments-type-specification/70963/2 "2021-11-04T16:32:11Z")

</div>

It’s not quite as convenient, but you can use `nothing` as the default and check for it:

```julia
julia> function g(a; b=nothing)
         if b === nothing
           b = ntuple(_ -> a, a)
         end
         b
       end
g (generic function with 1 method)

julia> g(2)
(2, 2)

julia> g(2, b=(3, 4))
(3, 4)

```

The `something` function can also make this easier:

```julia
julia> g(a; b=nothing) = something(b, ntuple(_ -> a, a))
g (generic function with 1 method)

julia> g(2)
(2, 2)

julia> g(2, b=(3, 4))
(3, 4)

```

```julia
help?> something
search: something

  something(x, y...)

  Return the first value in the arguments which is not equal to nothing, if any. Otherwise throw an error.
  Arguments of type Some are unwrapped.

```

---

<div class="post-metadata">

### Author: ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)
#### Post date: [November 4, 2021, 5:16pm UTC](https://discourse.julialang.org/t/use-function-argument-inside-optional-default-arguments-type-specification/70963/3 "2021-11-04T17:16:05Z")

</div>

The reason this doesn’t work is that `a` is a value that is not known until runtime.  
Apparently, you cannot depend a type signature (of `b`) on the runtime value of `a`.

The following would work:

```julia
julia> function g(::Val{a}, b::NTuple{a, Int64} = Tuple(repeat([a], a))) where a
           return b
       end
g (generic function with 2 methods)

julia> g(Val(2))
(2, 2)

julia> g(Val(3))
(3, 3, 3)

```

Of course, you can also do:

```julia
julia> function g2(a)
           Tuple(repeat([a], a))
       end
g2 (generic function with 1 method)

julia> g2(2)
(2, 2)

julia> g2(3)
(3, 3, 3)

julia> @code_warntype g2(3)
Variables
  #self#::Core.Const(g2)
  a::Int64

Body::Tuple{Vararg{Int64, N} where N}
1 ─ %1 = Base.vect(a)::Vector{Int64}
│ %2 = Main.repeat(%1, a)::Vector{Int64}
│ %3 = Main.Tuple(%2)::Tuple{Vararg{Int64, N} where N}
└── return %3

```

As `@code_warntype` displays, the function is type instable since the output type depends on the value of `a`. Such a pattern should be avoided in performance critical code.
