# Typing declaring Real numbers and using Vectors as default arguments

**URL:** <https://discourse.julialang.org/t/typing-declaring-real-numbers-and-using-vectors-as-default-arguments/81768>\
**Category:** General Usage\
**Tags:** question\
**Created:** [May 27, 2022, 8:02am UTC](https://discourse.julialang.org/t/typing-declaring-real-numbers-and-using-vectors-as-default-arguments/81768 "2022-05-27T08:02:40Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)\
**Post date:** [May 27, 2022, 8:02am UTC](https://discourse.julialang.org/t/typing-declaring-real-numbers-and-using-vectors-as-default-arguments/81768/1 "2022-05-27T08:02:40Z")

</div>

In Python I can make a method

```python
from typing import Optional, List
from numbers import Real
def mul(a, m:Optional[List[Real]]=None):
    m = [1,2] if m is None else m
    return a*m[0], a*m[1]

```

Which allows

```python
>>> mul(2)
(2, 4)
>>> mul(2,[10,20])
(20, 40)
>>> issubclass(int, Real)
True

```

Here, m has a default value of None which is then made into `[1,2]`. This is seen as good practice as `def mul(a, m = [1,2]):` can lead to unpredictable values of m. Additionally, `m` can take the form of any Real numbers (floats and ints).

In Julia I have

```nohighlight
function mul(a, m::Vector{Real}=[1,2])
    return a*m[1], a*m[2]
end

```

calling

```nohighlight
julia> mul(2)
ERROR: MethodError: no method matching mul(::Int64, ::Vector{Int64})
julia> Int64 <: Real
true

```

This confuses me. So by default `m` is a `Vector{Int64}` but which Julia says there’s no method for even though `Int64` is a _subtype_ of `Real`. There are two questions here:

1. How can I correctly label `mul` as requiring a vector of real numbers?
2. In Julia is it safe to have mutable objects as default values? `mul(a, m=[1,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:** [May 27, 2022, 8:24am UTC](https://discourse.julialang.org/t/typing-declaring-real-numbers-and-using-vectors-as-default-arguments/81768/2 "2022-05-27T08:24:03Z")

</div>

`Vector{S}` is not a subtype of `Vector{T}` even if `S <: T`. This is documented in the manual: [Types · The Julia Language](https://docs.julialang.org/en/v1/manual/types/#man-parametric-composite-types), and you can also find many discussions about it here: [Search results for 'invariant type' - JuliaLang](https://discourse.julialang.org/search?q=invariant%20type) The correct function signature for you is:

```julia
mul(a, m::Vector{<:Real}=[1,2])
# or
mul(a, m::Vector{T}=[1,2]) where {T<:Real}

```

The former is just syntactic sugar for the latter.

As for your second question, I’m not sure I understand. Safe in what way? I wouldn’t hesitate to use it, anyway. Why is the python version with `None` as default preferred?

BTW, since your function anyway returns a tuple, maybe you should allow tuple input?

---

<div class="post-metadata">

**Author:** ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)\
**Post date:** [May 27, 2022, 8:57am UTC](https://discourse.julialang.org/t/typing-declaring-real-numbers-and-using-vectors-as-default-arguments/81768/3 "2022-05-27T08:57:16Z")

</div>

Thank you. I’ve seen functions declared in this way but never really understood what is going on. I’ll implement this.

In place operations can cause unexpected behaviour as the default argument isn’t set each time the function is called, whereas it is when using `None` as default. Therefore, if mutable objects are the default and they’re changed inplace unexpected things can happen. See this silly example

```python
>>> def l(a=[2]):
... a.append(-1)
... print(len(a))
...
>>> l([1])
2
>>> l([1])
2
>>> l()
2
>>> l()
3
>>> l()
4

```

It seems Julia is safe against this, but I wasn’t sure whether there could be another reason to avoid.

That’s a great point, and another thing for me to learn how to do.

---

<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:** [May 27, 2022, 9:17am UTC](https://discourse.julialang.org/t/typing-declaring-real-numbers-and-using-vectors-as-default-arguments/81768/4 "2022-05-27T09:17:17Z")

</div>

Yes, Julia is safe against this. The default arguments are avaluated at run-time (at least it is guaranteed to behave that way).

```julia
mul(a, m=[1,2])

```

gets translated to

```julia
mul(a, m) = ...
mul(a) = mul(a, [1,2])

```

So you can do some things that Python cannot (I think), like

```julia
foo(x, y=2x)

```

Here, the default second argument depends on the first argument.

---

<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:** [May 27, 2022, 9:21am UTC](https://discourse.julialang.org/t/typing-declaring-real-numbers-and-using-vectors-as-default-arguments/81768/5 "2022-05-27T09:21:48Z")

</div>

> [@this\_josh](#):
>
> ```julia
> >>> l()
> 3
> >>> l()
> 4
> 
> ```

I must say, I find this pretty terrible. Isn’t this basically a bug? I mean, I know it is expected and probably documented, but it’s so strange and unnatural. It’s like a bug you can’t fix, so you just have to document it as “This doesn’t work right.”

Or does there exist some justification why this could be beneficial?

---

<div class="post-metadata">

**Author:** ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)\
**Post date:** [May 27, 2022, 9:34am UTC](https://discourse.julialang.org/t/typing-declaring-real-numbers-and-using-vectors-as-default-arguments/81768/6 "2022-05-27T09:34:47Z")

</div>

I didn’t realise you can doo `foo(x, y=2x)`, I like that.

I think mutable default arguments has been discussed a lot [this stack is 13 years old and references the official docs](https://stackoverflow.com/a/366430/5049813), it can also cause things to be a bit of mess if you use `lru_cache`. In general my python experience has made me very weary of inplace operations, which Julia uses extensively as they have benefits. But I still feel uncomfortable with them.

I’m not sure what the advantage would be, maybe saving a tiny bit of memory but at the cost of breaking “what you see is what you get”
