# Transposes vs 1-row matrices

**URL:** <https://discourse.julialang.org/t/transposes-vs-1-row-matrices/112652>\
**Category:** Internals & Design\
**Tags:** linearalgebra\
**Created:** [April 2, 2024, 7:11pm UTC](https://discourse.julialang.org/t/transposes-vs-1-row-matrices/112652 "2024-04-02T19:11:15Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 2, 2024, 7:11pm UTC](https://discourse.julialang.org/t/transposes-vs-1-row-matrices/112652/1 "2024-04-02T19:11:15Z")

</div>

> [@Is there a built-in function for the natural length of a segment represented by an iterator?](https://discourse.julialang.org/t/is-there-a-built-in-function-for-the-natural-length-of-a-segment-represented-by-an-iterator/112414/9):
>
> `diameter(itr) = [-1 1]*[extrema(itr)...]`

This will return a 1-element array. You could get a scalar out by using an [`Adjoint` vector](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#LinearAlgebra.Adjoint) instead via `[-1,1]'*[extrema(itr)...]` (see e.g. @jiahao’s [talk](https://www.youtube.com/watch?v=C2RO34b_oPM) on the meaning of transposition). But it’s a bit silly to allocate two arrays just to subtract two numbers.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [April 7, 2024, 2:43pm UTC](https://discourse.julialang.org/t/transposes-vs-1-row-matrices/112652/2 "2024-04-07T14:43:21Z")

</div>

> [@stevengj](#):
>
> This will return a 1-element array.

I still have some doubts:  
why does it return a vector with only one element and not a matrix with only one element?

For what (certainly excellent) reasons was it decided to differentiate the result in the two cases, also given that

```julia
julia> [1;1]' == [1 1]
true ?

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 7, 2024, 7:21pm UTC](https://discourse.julialang.org/t/transposes-vs-1-row-matrices/112652/3 "2024-04-07T19:21:38Z")

</div>

> [@rocco\_sprmnt21](#):
>
> why does it return a vector with only one element and not a matrix with only one element?

`[1 2]` in Julia is a 1x2 matrix (a 2d array). `[3, 4]` is a 1d array, interpreted as 2-component column vector. Any m \times n matrix times any n-component column vector yields an m-component column vector, so `[1 2] * [3, 4]` must therefore be a 1-component column vector (a 1d array with 1 element).

> [@rocco\_sprmnt21](#):
>
> For what (certainly excellent) reasons was it decided to differentiate the result in the two cases, also given that

See the talk I linked and the issue it is based on ([Taking matrix transposes seriously · Issue #20978 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/20978)).

TLDR: the adjoint x^\* (= transpose x^T for real vectors) of a column vector should “really” be a [covector](https://en.wikipedia.org/wiki/Linear_form) such that x^\* y is an inner product, yielding a scalar. (The whole reason why transposition is an important operation in linear algebra is due to its relationship to inner products.) Correspondingly, you really want `x' * y` to yield a scalar, not a 1-component vector, and all sorts of conventional linear-algebra expressions break if it doesn’t. On the other hand, it’s _also_ extremely common in linear algebra to identify covectors with “1-row matrices”, which is “really” just a very convenient isomorphism. So, as a compromise, after much discussion, it was eventually decided to make `x'` a special type (initially `RowVector` IIRC, now `Adjoint{eltype(x), typeof(x)}`), that acts like a covector in inner products (so that `x'y` returns a scalar) but which acts like a 1-row matrix for other operations (e.g. comparisons, stacking, iteration, …).

(Matlab sidesteps this whole issue because it equates scalars with 1 \times 1 matrices and column vectors with n \times 1 matrices … they are literally the [same type](https://www.mathworks.com/help/matlab/apiref/mxarray.html) under the hood. Introductory linear-algebra classes usually gloss over these distinctions too — when doing math by hand, you can usually tell what is intended from context, implicitly — but every semester there is inevitably some student question on [whether 1x1 matrices are equivalent to scalars](https://math.stackexchange.com/questions/65002/are-one-by-one-matrices-equivalent-to-scalars).)

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [April 8, 2024, 6:34am UTC](https://discourse.julialang.org/t/transposes-vs-1-row-matrices/112652/4 "2024-04-08T06:34:50Z")

</div>

Another consideration here is probably type stability. It would be quite bad if `*(::Matrix{Float64}, Vector{Float64})` could return either `Float64` or `Vector{Float64}`. With the `Adjoint` wrapper this is no longer ambiguous: `*(::Adjoint{Float64, Vector{Float64}}, ::Vector{Float64})` always gives `Float64` while the matrix variants always give `Vector{Float64}`.
