# Same expression returning inconsistent data types brings considerable inconvenience

**URL:** <https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469>\
**Category:** General Usage\
**Tags:** question\
**Created:** [April 24, 2024, 5:04pm UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469 "2024-04-24T17:04:52Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [April 24, 2024, 5:04pm UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/1 "2024-04-24T17:04:52Z")

</div>

For example,

```julia
function fun(ind)
    a = [1; 2]
    b = [3 4]
    return a[ind]' * reduce(vcat, b[ind])
end
fun([true; true])
fun([true; false])

```

the result is:

```julia
julia> fun([true; true])
11

julia> fun([true; false])
1×1 adjoint(::Vector{Int64}) with eltype Int64:
 3

```

Why do functions in Julia have inconsistent attitudes towards arrays? When `ind = [true; false]`, `a[ind]` is an `1-element Vector{Int64}` while `reduce(vcat, b[ind])` is just a scalar number.

This means a slight variation on the input parameter of a function that even doesn’t change the format or data type may result in quite different returns. (But I hope function `fun` can always return a scalar.)

This feature brings considerable inconvenience to coding, one of which is what I have mentioned in this post:

> [@How to make \`\[0\] == 0\`?](https://discourse.julialang.org/t/how-to-make-0-0/112630):
>
> julia\> 2 .- [1 1] \* [1; 1] == 0 false This means in Julia [0] != 0. Although I can understand this rule, I feel it inconvenient to use. Do I have to build awareness of this kind and to code carefully when using Julia, or is there any workaround to make it more convenient? Thanks

To distinguish between a scalar and an 1-element vector may be logically rigorous, but it seems to deviate from our convention. In particular, Julia, as a programming language that brings code closer to mathematical language (e.g., it supports LaTex characters), just happens to be less “mathematical” here, so why? Is this an advanced design with potential advantages (if so, what are the advantages?), or is it a primitive nature as a programming language?

In the end, I would like to ask everyone for advice on how to deal with such problems in linear algebra programming without making the code overly cumbersome?

Thanks!

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [April 24, 2024, 5:24pm UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/2 "2024-04-24T17:24:05Z")

</div>

I’m confused about why the `reduce` is necessary:

```julia
julia> function fun(ind)
           a = [1; 2]
           b = [3 4]
           return a[ind]' * b[ind]
       end
fun (generic function with 1 method)

julia> fun([true; true])
11

julia> fun([true; false])
3

```

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [April 24, 2024, 7:39pm UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/3 "2024-04-24T19:39:45Z")

</div>

The `reduce` is not just not needed, it is also to blame:

```julia-repl
julia> reduce(vcat, [1, 2])
2-element Vector{Int64}:
 1
 2

julia> reduce(vcat, [1])
1

# Always better to pass a suitable init element
julia> reduce(vcat, [1]; init = similar([1], 0))
1-element Vector{Int64}:
 1

```

On the other hand, boolean indexing is consistent and always returns a vector. Further, as explained in the other thread `u' * v` always gives a scalar for two vectors.

Also, did you intend to define `b` as a 1 \times 2 matrix or is a comma or semicolon missing?

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [April 25, 2024, 1:45am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/4 "2024-04-25T01:45:59Z")

</div>

> [@Sukera](#):
>
> why the `reduce` is necessary

I was just taking that as an example. Is there any proper situation that a `reduce` is needed?

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [April 25, 2024, 2:38am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/5 "2024-04-25T02:38:55Z")

</div>

How about the following example?

```julia
"""
Return the result of the following expression:
`c' * r`
where `r` is a random vector with a compatible dimension.
"""
function fun2(c)
    dim = length(c)
    r = rand(dim)
    return c' * r
end
fun2([1, 2])
fun2([1])
fun2(1)

```

The result is:

```julia
julia> fun2([1, 2])
1.97973421660914

julia> fun2([1])
0.7936651331121256

julia> fun2(1)
1-element Vector{Float64}:
 0.3585017443018734

```

What I want to say is that for the expression c^\top r, we mathematically allow c to degenerate into a scalar and the inner product degenerates into a product of two scalars thereby. So I can’t expect the users to be careful to write scalars as single-element vectors when entering function arguments (which is a bit unconventional). Then, who is responsible when the program goes wrong?

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [April 25, 2024, 2:53am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/6 "2024-04-25T02:53:20Z")

</div>

> [@WuSiren](#):
>
> I can’t expect the users to be careful to write scalars as single-element vectors when entering function arguments (which is a bit unconventional)

Is there a convenient method in Julia that can convert a variable into a vector when it is a scalar? Or I have to use `dot(a, b)` instead of the natural writing `a' * b` when calculating the inner product of two vectors?

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [April 25, 2024, 3:34am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/7 "2024-04-25T03:34:08Z")

</div>

We have mutiple dispatch in Julia. Please use it.

```julia-repl
julia> function fun2(c)
           dim = length(c)
           r = rand(dim)
           return c' * r
       end
fun2 (generic function with 1 method)

julia> fun2(c::Number) = fun2([c])
fun2 (generic function with 2 methods)

julia> fun2(1)
0.08685592968950084

```

---

<div class="post-metadata">

**Author:** ![screw\_dog](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/screw_dog/32/48119_2.png) [@screw\_dog](https://discourse.julialang.org/u/screw_dog)\
**Post date:** [April 25, 2024, 3:35am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/8 "2024-04-25T03:35:27Z")

</div>

Assuming your method signatures aren’t too complex, I’d just do something like:

```julia
function fun3(c::AbstractVector)
  # do stuff
  ...
end
fun3(c::Number) = fun3([c])

```

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [April 25, 2024, 4:01am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/9 "2024-04-25T04:01:52Z")

</div>

Thanks! That is a good idea! 🤝

However, what if the function has lots of similar arguments? Do I have to write methods for all the arguments one by one? For example,

```julia
function f(Params...)
    N = length(Params)
    S = 0
    for i = 1:N
        dim = length(Params[i])
        r = rand(dim)
        S += Params[i]' * r 
    end
    return S
end

```

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [April 25, 2024, 4:11am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/10 "2024-04-25T04:11:44Z")

</div>

Can I use some logic when defining a method? Something like:

```julia
function f(x::(Int64 ∪ Float64))
    return typeof(x)
end

```

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [April 25, 2024, 4:14am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/11 "2024-04-25T04:14:19Z")

</div>

The root of the problem here is that you’re using `length` to determine the size of the output of `rand`. This is inconsistent with what you’re trying to accomplish. Use `size` instead:

```julia
julia> function fun3(c)
           s = size(c)
           r = rand(s...)
           return c' * r
       end
fun3 (generic function with 1 method)

julia> fun3([1, 1])
1.0818115280587444

julia> fun3([1])
0.604859544315378

julia> fun3(1)
0.663513060981263

```

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [April 25, 2024, 4:26am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/12 "2024-04-25T04:26:10Z")

</div>

Thank you very much! I was just about to point out the problem with `length` and `size`, although your reply has given me a lot of inspiration.

```julia
julia> length([1, 2])
2

julia> length([1])
1

julia> length(1)
1

julia> size([1, 2])
(2,)

julia> size([1])
(1,)

julia> size(1)
()

julia> struct NewDT end

julia> length([NewDT(), NewDT()])
2

julia> length([NewDT()])
1

julia> length(NewDT())
ERROR: MethodError: no method matching length(::NewDT)

julia> size([NewDT(), NewDT()])
(2,)

julia> size([NewDT()])
(1,)

julia> size(NewDT())
ERROR: MethodError: no method matching size(::NewDT)

```

Why can’t `length` and `size` work well with user-defined data type?

```julia
julia> typeof(1)
Int64

julia> typeof(NewDT())
NewDT

```

How should I get the length or size of a `Vector{NewDT}` or scalar `NewDT`?

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [April 25, 2024, 5:07am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/13 "2024-04-25T05:07:40Z")

</div>

```julia
julia> struct NewDT end

julia> Base.length(::NewDT) = 1

julia> Base.size(::NewDT) = ()

julia> length(NewDT())
1

julia> size(NewDT())
()

julia> size([NewDT()])
(1,)

julia> length([NewDT()])
1

```

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [April 25, 2024, 5:11am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/14 "2024-04-25T05:11:44Z")

</div>

> [@WuSiren](#):
>
> Can I use some logic when defining a method? Something like:
> 
> ```julia
> function f(x::(Int64 ∪ Float64))
> return typeof(x)
> end
> 
> ```

```julia-repl
julia> function f(x::Union{Float64,Int64})
           return typeof(x)
       end
f (generic function with 1 method)

julia> f(5)
Int64

julia> f(5.0)
Float64

julia> f(3.f0)
ERROR: MethodError: no method matching f(::Float32)
The function `f` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  f(::Union{Float64, Int64})
   @ Main REPL[18]:1

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [April 25, 2024, 6:17am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/15 "2024-04-25T06:17:53Z")

</div>

> [@WuSiren](#):
>
> Is there any proper situation that a `reduce` is needed?

Sure, if you’re passing a collection/iterator of collections that you want to consolidate. I don’t know of a use when you’re only interested in linear algebra though, and I wouldn’t think of using it in that context either. Julia is not exclusively built for linear algebra.

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [April 29, 2024, 8:23am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/16 "2024-04-29T08:23:39Z")

</div>

If there is a function with a matrix `A` as its input argument, is it my duty to consider the degenerate types of `A` (e.g., a vector or even a scalar number) or the user’s duty to input the argument strictly in matrix type when invoking the function? Which is more Julian?

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [April 29, 2024, 8:37am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/17 "2024-04-29T08:37:37Z")

</div>

> [@WuSiren](#):
>
> the degenerate types of `A` (e.g., a vector or even a scalar number)

The type system distinguishes between matrices, vectors and scalars. Example:

```julia-repl
julia> s = 7
7

julia> v = [7, 8]
2-element Vector{Int64}:
 7
 8

julia> m = [7 8]
1×2 Matrix{Int64}:
 7 8

julia> s isa AbstractMatrix
false

julia> v isa AbstractMatrix
false

julia> m isa AbstractMatrix
true

```

The method dispatch relies on the type system (multiple dispatch). Start using that while writing code.

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [April 29, 2024, 8:47am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/18 "2024-04-29T08:47:04Z")

</div>

Yes, I’m aware of this. Thanks.

My argument is (hopefully not the case) that this setup not only leads to some inconsistencies within the Julia language ecosystem (e.g., see [this post](https://discourse.julialang.org/t/how-to-make-0-0/112630/15)) but also brings certain inconveniences to programming, especially in the field of mathematics.

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [April 29, 2024, 8:53am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/19 "2024-04-29T08:53:10Z")

</div>

> [@nsajko](#):
>
> Start using that while writing code.

I’m trying to use multiple dispatch, but I’m running into some trouble. For example, I have a function that takes multiple input parameters and is implemented as a matrix operation for all the input parameters. However, when calling the function, some or all of the input parameters may degrade to vectors or scalars, which also make sense mathematically. Do I need to separately write degraded form methods for each parameter?

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [April 29, 2024, 8:55am UTC](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469/20 "2024-04-29T08:55:12Z")

</div>

> [@WuSiren](#):
>
> when calling the function, some or all of the input parameters may degrade to vectors or scalars

That’s not a thing in Julia. Can you give a specific example.

[Next page](https://discourse.julialang.org/t/same-expression-returning-inconsistent-data-types-brings-considerable-inconvenience/113469.md?page=2)
