Taking Vector Transposes Seriously | Jiahao Chen | JuliaCon 2017

Taking Vector Transposes Seriously | Jiahao Chen | JuliaCon 2017 — The Julia Programming Language

The Julia Programming Language

AI-assisted summary of Taking Vector Transposes Seriously | Jiahao Chen | JuliaCon 2017 — original source. Check the original for full context.

Source published:

Key ideas

  • Debates over vector transposition in Julia (GitHub issue #4774) and Python trace back to a fundamental historical division between matrix theory and abstract vector space theory prior to their 1960s unification. (0:00)
  • Julia 0.5 produced unexpected 1-element vectors instead of scalars for inner products ($u'v$) because vector transposition was defined by promoting vectors to column matrices before transposing. (9:45)
  • Chen presents an impossibility result demonstrating that a scientific computing language cannot fully support standard Householder notation using only three types (scalars, vectors, and matrices). (13:40)
  • Julia solved the dilemma by introducing a dedicated fourth type, `RowVector`, leveraging multiple dispatch to consistently evaluate inner, outer, and bilinear forms. (13:40)

Detailed notes

## Background Published on YouTube by The Julia Programming Language channel on July 17, 2017, this JuliaCon 2017 presentation features Jiahao Chen discussing vector transpositions. The video description invites viewers to download Julia from julialang.org and encourages community participation in contributing timestamps and improved captions.

## TL;DR Jiahao Chen explores the contentious debate surrounding vector transposes in Julia, tracing the friction back to a historical schism between matrix theory and abstract vector space algebra. He proves that satisfying standard Householder notation with only three core types—scalars, vectors, and matrices—is mathematically impossible, which previously caused operations like inner products to return awkward 1-element vectors in Julia 0.5. By contrasting approaches in languages like MATLAB and Lua, Chen demonstrates why Julia adopted a four-type system incorporating a dedicated `RowVector` type. This architectural choice leverages polymorphic multiple dispatch to maintain mathematical rigor and intuitive notation without relying on ad hoc parsing hacks.

## Atmosphere & style The presentation is candid, intellectually playful, and deeply engaging, striking a balance between historical scholarship and practical language design. Chen sets an approachable, humorous tone from the start, playfully disclaiming his new employer, joking about stock photos of 'unhappy mathematicians,' and openly admitting that the Julia core team had initially been mistaken on multiple fronts. Watching it feels like attending an insider post-mortem where rigorous mathematical philosophy meets pragmatic engineering, culminating in a warm round of community applause for the developers who turned theory into working code.

## Bulletin - [00:00](https://www.youtube.com/watch?v=C2RO34b_oPM&t=0s) Debates over vector transposition in Julia (GitHub issue #4774) and Python trace back to a fundamental historical division between matrix theory and abstract vector space theory prior to their 1960s unification. - [09:45](https://www.youtube.com/watch?v=C2RO34b_oPM&t=585s) Julia 0.5 produced unexpected 1-element vectors instead of scalars for inner products ($u'v$) because vector transposition was defined by promoting vectors to column matrices before transposing. - [13:40](https://www.youtube.com/watch?v=C2RO34b_oPM&t=820s) Chen presents an impossibility result demonstrating that a scientific computing language cannot fully support standard Householder notation using only three types (scalars, vectors, and matrices). - [13:40](https://www.youtube.com/watch?v=C2RO34b_oPM&t=820s) Julia solved the dilemma by introducing a dedicated fourth type, `RowVector`, leveraging multiple dispatch to consistently evaluate inner, outer, and bilinear forms.

## Key takeaways - [00:00](https://www.youtube.com/watch?v=C2RO34b_oPM&t=0s) GitHub issue #4774, 'Taking vector transposes seriously,' emerged as one of the most contentious debates in the Julia community, echoing similar extensive disputes in Python. - [01:28](https://www.youtube.com/watch?v=C2RO34b_oPM&t=88s) User dissatisfaction in Julia stemmed from inner products returning 1-element arrays rather than true scalars, breaking chained mathematical expressions. - [01:28](https://www.youtube.com/watch?v=C2RO34b_oPM&t=88s) The conceptual friction originates from two distinct mathematical views: vectors as columns of a matrix ('column vectors') versus vectors as elements of an abstract vector space ('flat vectors'). - [03:20](https://www.youtube.com/watch?v=C2RO34b_oPM&t=200s) Historically, matrices and abstract vectors evolved as completely separate fields between 1924 and 1960 before modern mathematics unified them and treated their equivalence as self-evident. - [04:58](https://www.youtube.com/watch?v=C2RO34b_oPM&t=298s) Foundational texts by van der Waerden and L. L. Thurstone explicitly distinguished abstract vectors, scalar coefficients, tuples, and column matrices. - [07:08](https://www.youtube.com/watch?v=C2RO34b_oPM&t=428s) Householder notation relies on two hidden isomorphisms: converting vectors to column matrices and converting resulting 1×1 matrices back into scalars. - [09:45](https://www.youtube.com/watch?v=C2RO34b_oPM&t=585s) Julia 0.5 treated vector transpose as promotion to a matrix followed by matrix transpose, causing expressions like $u'v$ to evaluate to non-scalar 1-element vectors. - [11:02](https://www.youtube.com/watch?v=C2RO34b_oPM&t=662s) MATLAB circumvents vector ambiguities by treating the matrix as its only primitive data type and employing a trailing singleton dimension rule. - [11:02](https://www.youtube.com/watch?v=C2RO34b_oPM&t=662s) Adopting MATLAB-style shape coercion in Julia would break composition and require fragile parsing rules or compound operators. - [13:40](https://www.youtube.com/watch?v=C2RO34b_oPM&t=820s) A 2×2 classification proves that a system constrained to scalars, vectors, and matrices inevitably breaks inner products, outer products, or bilinear forms. - [14:53](https://www.youtube.com/watch?v=C2RO34b_oPM&t=893s) Across languages, vector transpose is handled inconsistently: Lua raises errors, NumPy and Mathematica treat it as an identity operation, and R coerces expressions to matrices. - [13:40](https://www.youtube.com/watch?v=C2RO34b_oPM&t=820s) Julia resolved Householder notation consistency by introducing a dedicated fourth primitive type: `RowVector`. - [16:19](https://www.youtube.com/watch?v=C2RO34b_oPM&t=979s) Expanding multiplication methods to accommodate `RowVector` mirrors how students naturally learn increasingly general arithmetic and algebra systems. - [17:48](https://www.youtube.com/watch?v=C2RO34b_oPM&t=1068s) Implementing a fully consistent linear algebra syntax under multiple dispatch fundamentally requires at least four distinct mathematical types.

## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=C2RO34b_oPM&t=0s) The Contested Vector Transpose in Julia and Beyond

Jiahao Chen introduces himself, noting that until roughly four months prior he was at MIT CSAIL with the Julia Lab, and currently works at Capital One in New York. He clarifies that all the work presented was done before joining Capital One, so the company cannot dictate what he can or cannot say about the topic. Chen brings up the widely recognized GitHub issue titled "Taking vector transposes seriously" (issue #4774), asking the audience how many have read it. When about three-quarters of the room raise their hands, he delivers the central premise: “the punch line here is that we were wrong on at least four counts on this issue and I will explain as much as possible within half an hour why we were wrong”.

Chen describes issue #4774 as possibly one of the most hotly debated topics in the Julia community. He polled several community luminaries for their views, presenting contrasting slides of opinions, including one from a prominent member who could not attend the conference. It turns out Julia is not alone in grappling with this: the Python community also had an extensive debate over vector transposes and dimensions, generating some 381 comments on a single issue. The topic reliably agitates developers and mathematicians across programming ecosystems.

[01:28](https://www.youtube.com/watch?v=C2RO34b_oPM&t=88s) The Surface Problem: Unhappy Mathematicians and Dual Definitions

Chen presents the surface issue facing users in Julia 0.6. Displaying a picture of an "unhappy mathematician" (the first image returned by Google for the term, which Chen jokes he used directly), he mimics the typical user complaint: someone tries to compute an inner product, Julia returns a 1-element array instead of a scalar, and attempting to chain it into a larger mathematical expression throws an error, leaving them frustrated and asking: "don't you Julia people know any mathematics?" The core Julia developers' initial instinct was to question: “why would you want to do that okay why do people want to write inner products like this and why do people get so worked up about this issue”.

After researching the matter, Chen concludes that the conflict stems from fundamentally conflicting ideas of what a vector actually is. In mathematics, two distinct definitions coexist: 1. A vector is a column of a matrix. 2. A vector is that which obeys the algebra of a vector space.

While naturally isomorphic, these two notions are not identical. A Type 1 vector (a column of a matrix) clearly satisfies the algebra of a vector space, but not all vectors in a vector space are columns of matrices. To keep them clear throughout the presentation, Chen terms them **column vectors** and **flat vectors**.

```mermaid flowchart TD accTitle: Two Incompatible Definitions of Vectors accDescr: Diagram contrasting Column Vectors and Flat Vectors in mathematics and linear algebra. subgraph Defs["Mathematical Definitions"] CV["Column Vector<br>(Column of a Matrix)"] FV["Flat Vector<br>(Object in an Abstract Vector Space)"] end CV -.->|"Naturally isomorphic,<br>but not identical"| FV CV -->|"Has vector space algebra"| Alg["Vector Space Algebra"] FV -->|"Has vector space algebra"| Alg FV -.->|"Not necessarily"| Mat["Matrix Columns"] ```

[03:20](https://www.youtube.com/watch?v=C2RO34b_oPM&t=200s) The Historical Schism: Matrices vs. Vector Spaces

Investigating how these duplicate definitions originated, Chen traced the history of linear algebra. Between roughly 1924 and 1960, a historical division existed between matrix theory and vector spaces: “there was once a universe where matrices were their own subject and vectors were their own subject and these two subjects did not mix whatsoever and at some point they merged and and we work in the world of the the post merger universe of matrices and vectors”.

In the matrix-only universe, textbooks spoke of "column matrices" and used the rectangular notation familiar today. In the vector universe, mathematicians worked with vector space axioms, coordinate geometry, and the concept of an ordered tuple. In the 1920s, mathematicians observed that column matrices themselves form a vector space, creating a merged framework where the column definition is paradoxically both older and newer than the abstract definition. Chen simplifies this transition with a three-stage timeline: - The **pre-unification era**, where matrices and vectors existed as separate fields. - The **early unification era**, where textbooks had to explain the relationship very carefully. - The **modern era**, where the equivalence is treated as so obvious that everyone is expected to have learned it in elementary school.

```mermaid flowchart LR accTitle: Historical Evolution of Matrix and Vector Theory accDescr: Three eras showing how matrices and vectors began separately, unified, and became a modern standard. subgraph Era1["Pre-Unification Era"] M1["Matrix Universe<br>(Column matrices, rectangular arrays)"] V1["Vector Universe<br>(Axioms, coordinate geometry, tuples)"] end subgraph Era2["Early Unification (1924–1960)"] U["Merged View<br>(Careful proofs that column matrices form vector spaces)"] end subgraph Era3["Modern Era"] Std["Unified Standard<br>(Householder notation, taken for granted)"] end M1 --> U V1 --> U U --> Std ```

[04:58](https://www.youtube.com/watch?v=C2RO34b_oPM&t=298s) Historical Textbooks: van der Waerden and Thurstone

To illustrate the early unification era, Chen examines B. L. van der Waerden's foundational textbook *Moderne Algebra* (Modern Algebra), which helped define modern abstract algebra. In English translation, the text carefully distinguishes its terms: - **Vectors** are the abstract objects endowed with the algebraic operations of a vector space. - **Coefficients** (elements of what we would now call a ring or field) represent the scalar numbers. - **Tuples** are indexable collections of these coefficients, but have no intrinsic algebra defined on them. - A **column matrix** is a separate construct from linear algebra that can be associated with a vector.

Chen emphasizes that in this formulation, the algebra lives entirely within the vector; scalars provide the coefficients, tuples merely store them without algebraic structure, and column matrices belong to the distinct field of matrix algebra.

Chen also highlights L. L. Thurstone’s 1935 psychometrics/statistics text, *The Vectors of Mind: Multiple Factor Analysis for the Isolation of Primary Traits*. Thurstone explicitly bridged the gap, writing that if a matrix has a single column it is termed a column vector, if it has a single row it is a row vector, and that this vectorial terminology was primarily a consequence of geometric interpretation.

[07:08](https://www.youtube.com/watch?v=C2RO34b_oPM&t=428s) Householder Notation and Hidden Isomorphisms

Moving forward to 1953, the birth of modern numerical analysis codified the language used by practitioners today via **Householder notation**: - Small Greek letters for scalars ($\alpha, \beta$). - Small Roman letters for vectors ($u, v$). - Capital Roman letters for matrices ($A, B$).

In this system, fundamental operations are composed from just two building blocks: transposition ($'$) and multiplication ($*$). - Inner product: $u'v$ (yields a scalar). - Outer product: $uv'$ (yields a matrix). - Bilinear form: $u'Av$ (yields a scalar).

Chen argues that virtually all complex matrix-vector expressions reduce to compositions of these elementary operations. However, writing $u'v$ as a vector-vector operation returning a scalar relies on hidden assumptions. When modeled rigorously, the expression requires two implicit isomorphisms: 1. Converting the vector into a column matrix (so matrix transpose and matrix multiplication apply). 2. Converting the resulting $1 \times 1$ matrix back into a true scalar.

Chen stresses that “it comes down to the Crux really of whether or not you want your language to deal with these isomorphisms for you or whether you want to deal with them yourself”.

[09:45](https://www.youtube.com/watch?v=C2RO34b_oPM&t=585s) How Julia 0.5 Broke Vector Transposition and the MATLAB Comparison

Chen explains that Julia prior to version 0.6 adopted a literal interpretation: it defined vector transposition as promoting the vector to a matrix and then executing a matrix transpose. Decomposing $u'v$ under that model produced severe, counterintuitive bugs. The left-hand vector $u$ was promoted to a column matrix, transposed to a $1 \times n$ row matrix, and then multiplied by the column vector $v$. By standard matrix rules, a matrix-vector product yields a vector—specifically a 1-element vector.

A 1-element vector is fundamentally different from a scalar: you cannot divide by it, and it lacks scalar arithmetic. While a $1 \times 1$ matrix can reasonably act as a scalar surrogate, a 1-element flat vector cannot, leaving users stranded with unexpected types and syntax errors (symbolized on the slide by an "unhappy Einstein"). Finally, Chen points toward MATLAB, arguing that MATLAB is an anomaly among modern programming languages, which explains why developers and language designers feel so much friction trying to adapt its matrix-centric behaviors to modern, rigorously typed languages.

[11:02](https://www.youtube.com/watch?v=C2RO34b_oPM&t=662s) MATLAB's Matrix-Only Model and Language Design Trade-offs

Jiahao Chen explains that MATLAB avoids many vector ambiguity issues because its design is firmly rooted in "Type 1" vectors—vectors treated fundamentally as column matrices. To illustrate this philosophy, he shares two quotes from MATLAB documentation spanning decades. The first comes from the original 1980 Matrix Laboratory report from the University of New Mexico when Cleve Moler was still on the faculty:

> “In MATLAB, the matrix is the only data type, with scalars, vectors, and text as special cases.”

The second citation is from the MATLAB manual published the previous year, which continues to state that matrices with dimension equal to one on one side and greater than one on the other side are called vectors. Because everything in MATLAB is a matrix, values are coerced on demand to vectors or scalars via the "trailing singleton dimension rule," where dimensions of length one at the end of an array can be added or dropped at will. In this system, vector-matrix isomorphisms simply reduce to dropping or appending trailing indices. Furthermore, operations can halt at a $1 \times 1$ matrix expression rather than forcing conversion to a true scalar.

While elegant within its own paradigm, this approach clashes with Julia’s dispatch philosophy. Supporting shape-based behavior in multiplication forces special-casing $1 \times 1$ matrices on the left and right. More broadly, if a language relies solely on transpose and multiplication without careful type distinctions, it must either define them with fragile parsing rules or treat expressions like $x' \cdot y$ as ad hoc compound operators. Chen notes that introducing special parsing rules breaks composition—such as when inadvertently inserting parentheses changes the resulting type—and adds language complexity that designers like Jeff Bezanson would caution against.

[13:40](https://www.youtube.com/watch?v=C2RO34b_oPM&t=820s) The 2×2 Impossibility Result and the Need for Row Vectors

Chen formalizes the design space for systems limited to three core types: scalars, vectors, and matrices. If a language only has these three types, a $2 \times 2$ grid of design choices emerges based on whether matrix-vector products yield vectors or column matrices, and whether transposing a vector returns a row matrix or the vector itself.

Chen demonstrates that within this three-type constraint, fully adhering to Householder notation is mathematically impossible: - Some choices break inner products (the flaw present in older versions of Julia). - Other quadrants break outer products. - The remaining quadrants break quadratic products and bilinear forms.

Chen summarizes this central theoretical result:

> “So that's our, that's our main result here, that you can't have what you want.”

To resolve this impasse, Julia introduced a dedicated `RowVector` type. By combining row vectors with type-based multiple dispatch, all expressions in Householder notation evaluate consistently:

> “The moral of the story is that you can't get what you want for Householder with three types, but you can with four.”

```mermaid flowchart TD accTitle: Vector Transpose Approaches Across Programming Languages accDescr: A comparison showing how different languages handle vector transposition and Julia's four-type solution.

subgraph ThreeType["3-Type Systems (Scalars, Vectors, Matrices)"] A["Vector Transpose v'"] A -->|"Error"| B["Lua"] A -->|"Identity"| C["NumPy / Mathematica / SciRuby"] A -->|"Matrix Output"| D["R (Linear algebra yields matrices)"] A -->|"Singleton Dimensions"| E["MATLAB (Everything is a matrix)"] end

subgraph FourType["4-Type Systems (+ RowVector)"] F["v' Yields RowVector"] F --> G["Pari/GP (Explicit conversions)"] F --> H["New Julia (Dispatch-driven)"] end ```

[14:53](https://www.youtube.com/watch?v=C2RO34b_oPM&t=893s) How Other Languages Handle Vector Transposition

Looking across the broader scientific computing ecosystem, Chen highlights the disparate strategies language designers have used for vector transposition: - **Error:** In Lua, transposing a 1D vector is simply an invalid operation. - **Identity:** In NumPy, Mathematica, and SciRuby, the transpose of a 1D vector is the vector itself ($v^T = v$). - **Matrix-heavy conversions:** In R, invoking transpose or matrix multiplication automatically promotes results to matrices. MATLAB conceptually aligns here, though it lacks distinct scalar or vector types altogether. - **Explicit Row Types:** PARI/GP, a language used for number-theoretic computations, shares modern Julia's approach of having an explicit row representation, though it requires explicit conversions between columns, rows, and matrices.

Chen points out that several corners of this taxonomic design space remain completely unexplored, jokingly offering them as ideas for anyone in the audience designing a new programming language.

[16:19](https://www.youtube.com/watch?v=C2RO34b_oPM&t=979s) Polymorphic Multiplication and Natural Mathematics

Implementing row vectors requires adding specific method definitions for `transpose` and `*`, but it keeps user code simple by letting dispatch resolve the operations cleanly. Chen anticipates the objection that adding definitions bloats the method table, displaying a slide where the sheer volume of multiplication methods requires shrinking everything past the first definition to a tiny 1.5-point font.

Despite this, Chen argues that multiple dispatch mirrors how people actually learn mathematics: - Students begin with multiplication tables: $\text{Int} \times \text{Int}$. - They advance to fractions: $\text{Rational} \times \text{Int}$. - They progress to real numbers and decimals: $\text{Real} \times \text{Real}$. - Advanced schooling introduces complex numbers ($\text{Complex} \times \text{Complex}$) and matrix-vector operations ($\text{Matrix} \times \text{Vector}$).

Extending multiplication to handle `RowVector * Matrix` or `RowVector * Vector` is simply a natural continuation of this progression.

[17:48](https://www.youtube.com/watch?v=C2RO34b_oPM&t=1068s) Conclusion and Acknowledgments

Chen fast-forwards through his remaining slides to leave time for audience questions, concluding that the Julia community has finally taken vector transposes seriously. He gives special recognition to Andy Ferris, calling him out in the audience for a round of applause:

> “As you know, it was my, it was my privilege as an academic to just speculate about what to do, but Andy actually did it, so that also deserves plenty of credit.”

Reflecting on the entire exercise, Chen emphasizes that the community had forgotten how difficult these foundational ideas once were. Programmers had grown blind to the explicit isomorphisms required to bridge flat vectors with column matrices, and overlooked that multiplication is fundamentally polymorphic. The definitive takeaway of the work is that implementing consistent Householder notation within a type-based dispatch system requires a minimum of four distinct types.

## Notable quotes > [11:02](https://www.youtube.com/watch?v=C2RO34b_oPM&t=662s) In MATLAB, the matrix is the only data type, with scalars, vectors, and text as special cases. — Cleve Moler

## Mentioned Jiahao Chen, Andy Ferris, Cleve Moler, B. L. van der Waerden, L. L. Thurstone, Alston Scott Householder, Jeff Bezanson, Julia, MATLAB, Python, NumPy, Lua, R, PARI/GP, Mathematica, SciRuby, MIT CSAIL, Capital One, Moderne Algebra, The Vectors of Mind

## Video description Visit http://julialang.org/ to download Julia. Time Stamps:

00:00 Welcome! 00:10 Help us add time stamps or captions to this video! See the description for details.

Want to help add timestamps to our YouTube videos to help with discoverability? Find out more here: https://github.com/JuliaCommunity/YouTubeVideoTimestamps

Interested in improving the auto generated captions? Get involved here: https://github.com/JuliaCommunity/YouTubeVideoSubtitles

[Source](https://www.youtube.com/watch?v=C2RO34b_oPM)

中文简报

认真对待向量转置 | 陈家豪 | JuliaCon 2017 陈家豪探讨了围绕 Julia 中向量转置的激烈争论,将这一分歧追溯至矩阵理论与抽象向量空间代数之间的历史分歧。他证明了仅使用标量、向量和矩阵这三种核心类型,在数学上不可能完全满足标准的 Householder 记号,这也曾导致 Julia 0.5 中的内积等运算产生别扭的单元素向量。通过对比 MATLAB 和 Lua 等语言的处理方式,陈家豪阐释了为何 Julia 采用包含专门 `RowVector` 类型的四类型系统。这一架构选择利用多态多重分派,在不依赖临时解析手段的情况下,保持了数学的严密性与直观的记号。 Julia(GitHub issue #4774)和 Python 中关于向量转置的争论,可追溯到 1960 年代矩阵理论与抽象向量空间理论统一之前两者在历史上的根本分歧。 (0:00) Julia 0.5 在计算内积($u'v$)时产生了意外的单元素向量而非标量,因为向量转置曾被定义为在转置前将向量提升为列矩阵。 (9:45) 陈家豪提出了一项不可行性结果,证明科学计算语言如果仅使用三种类型(标量、向量和矩阵),在数学上不可能完全支持标准的 Householder 记号。 (13:40) Julia 通过引入专门的第四种类型 `RowVector` 解决了这一困境,利用多重分派来一致地计算内积、外积和双线性型。 (13:40)

Reading summary

Jiahao Chen argues that the persistent controversy over vector transposes in technical computing arises from an unresolved historical split between matrix algebra and abstract vector spaces. He demonstrates that supporting standard Householder notation in a typed language is mathematically impossible with only three core types (scalars, vectors, and matrices), necessitating a dedicated fourth type: row vectors. The Historical Split: Column Matrices Versus Vector Spaces (3:20) The recurring friction in technical computing environments like Julia and Python over vector transposition stems from two historically distinct concepts. Between 1924 and roughly 1960, matrix theory and vector spaces existed as separate fields. In textbooks such as B. L. van der Waerden's Moderne Algebra (1930), vectors carried abstract vector space algebra, coefficients supplied scalar values, tuples acted as raw indexable storage without intrinsic algebra, and column matrices formed a distinct concept in linear algebra. In 1935, L. L. Thurstone explicitly bridged this divide in psychometrics by classifying single-column matrices as column vectors and single-row matrices as row vectors based on geometric interpretation. By 1953, Alston Householder codified modern notation relying on small Greek letters for scalars, small Roman letters for vectors, and capital Roman letters for matrices, built around transposition and multiplication. However, treating an inner product like u'v as returning a scalar relies on two hidden isomorphisms: coercing an abstract flat vector into a column matrix, and subsequently coercing the resulting 1x1 matrix back into a scalar. Modern languages must decide whether to handle these isomorphisms automatically or force users to manage them explicitly. Julia 0.5 Failures and the MATLAB Anomaly (9:45) Prior to version 0.6, Julia defined vector transposition by promoting a vector to a column matrix and taking its matrix transpose into a 1xn row matrix. Multiplying this row matrix by a standard vector yielded a 1-element vector rather than a scalar under matrix-vector rules. Because a 1-element vector lacks scalar arithmetic and cannot be divided by, chained mathematical operations failed with unexpected type errors. Chen contrasts this with MATLAB, which he characterizes as an anomaly among modern programming languages. Since its inception in 1980 under Cleve Moler, MATLAB has treated matrices as the sole data type, viewing scalars and vectors as mere special cases. MATLAB relies on a trailing singleton dimension rule that drops or appends dimensions of length one on demand. While this approach avoids scalar-vector type conflicts by halting at 1x1 matrices, adopting shape-based coercions in Julia would break multiple dispatch, require fragile ad hoc parsing rules, and destroy compositionality. The Three-Type Impossibility and the Four-Type Solution (13:40) Chen formalizes the design space for systems restricted to three foundational types: scalars, vectors, and matrices. In a 2x2 grid testing whether vector transposes yield row matrices or vectors, and whether matrix-vector products return vectors or column matrices, every configuration fails at least one standard operation. Depending on the quadrant chosen, the system breaks inner products, outer products, quadratic forms, or bilinear forms. Chen concludes that within a three-type system, satisfying Householder notation is mathematically impossible. To resolve this impossibility, Julia adopted a four-type system implemented by Andy Ferris, introducing a dedicated RowVector type. When paired with polymorphic multiple dispatch, having four types allows u' to evaluate to a row vector, u'v to yield a true scalar, and uv' to yield an outer product matrix. Across other languages, solutions remain fragmented: Lua throws an error on 1D vector transposition, NumPy and Mathematica treat it as an identity operation, R and MATLAB lean entirely on matrix promotions, and PARI/GP employs explicit row types requiring manual conversions. Polymorphic Multiplication and Mathematical Pedagogy (16:19) Introducing a distinct row vector type requires defining specialized methods for transpose and multiplication, substantially enlarging the language's method table. Chen argues that this complexity is well justified because multiple dispatch reflects how mathematics is naturally taught and learned. Educational progression moves sequentially from integers to rationals, reals, complex numbers, and eventually matrix-vector operations. Extending multiplication dispatch to handle combinations like RowVector * Matrix and RowVector * Vector is simply a logical continuation of standard polymorphic mathematical operations. Chen concludes that mathematical programming communities took vector transposes for granted by forgetting the historical difficulties and implicit isomorphisms required to unify abstract vectors with column matrices. By formally expanding the type system from three types to four, languages can natively support standard Householder notation without resorting to ad hoc parsing rules or singleton dimension hacks.

精炼阅读摘要

Jiahao Chen 在 JuliaCon 2017 演讲中指出,科学计算语言中关于向量转置的长期争论源于线性代数发展史上对“列矩阵”与“抽象向量空间”的双重定义冲突;在严格类型系统中,若仅依赖标量、向量和矩阵三种类型,无法在数学上自洽地支持 Householder 记号,必须引入第四种类型——行向量(RowVector)。 表面困境与双重定义的历史分歧 (1:28) 在 Julia 0.6 之前的开发与使用中,向量转置(GitHub issue #4774)引发了社区乃至整个科学计算领域的广泛争议,Python 社区也曾为此产生过 381 条讨论。数学用户常抱怨计算内积时系统返回单元素数组(1-element array)而非标量,导致链式数学表达式报错崩溃。Jiahao Chen 指出,这一摩擦的根源在于数学体系内并存且未被严格区分的两种向量概念:一是指矩阵的列(列向量),二是指服从向量空间代数公理的抽象对象(扁平向量)。两者虽然自然同构,但并不等同,并非所有抽象向量本质上都是矩阵的列。 历史融合与 Householder 记号的隐式同构 (3:20) 从线性代数发展史来看,1924 年至 1960 年间矩阵理论与向量空间曾是互不干涉的独立学科。B. L. van der Waerden 在《代数学》(Moderne Algebra)中对向量、系数、无代数结构的多元组(tuple)和列矩阵进行了严格界分;1935 年 L. L. Thurstone 的著作则因几何解释将单列和单行矩阵分别称作列向量与行向量。直到 1953 年现代数值分析建立,Householder 记号确立了希腊字母代表标量、小写字母代表向量、大写字母代表矩阵的标准,仅通过转置(')和乘法(*)构建内积(u'v)、外积(uv')和双线性型(u'Av)。但 Chen 强调,u'v 能得到标量依赖于两个隐藏的隐式同构:首先将向量提升为列矩阵以执行矩阵运算,再将运算后得到的 1×1 矩阵折叠回真正的标量。这迫使编程语言设计者必须抉择是由底层系统处理这些同构,还是交由用户手动维护。 三种类型的二乘二不可能结果与 MATLAB 方案的局限 (11:02) MATLAB 之所以能够平滑处理这些运算,是因为它自 1980 年诞生起就遵循“一切皆矩阵”的单类型哲学,标量与向量仅是特殊情况,并通过“末尾单一维度规则”(trailing singleton dimension rule)在数组末尾随意增删大小为 1 的维度,将同构问题弱化。然而,这种依靠形状判断而非类型的规则破坏了函数组合性,如果随意加括号改变类型或引入脆弱的解析规则,将违背 Julia 的多重分派设计。Chen 提出了“2×2 不可能结果”定理:若系统中仅包含标量、向量和矩阵这三种类型,无论如何组合“矩阵乘以向量是向量还是列矩阵”以及“向量转置是行矩阵还是自身”,在四个象限中至少会破坏内积、外积或双线性型中的一种,导致完整的 Householder 记号无法成立。 引入行向量实现多态分派与跨语言对比 (14:53) 为破解三种类型的数学僵局,Julia 借鉴了 PARI/GP 等语言显式区分行对象的思路,正式引入了独立的 `RowVector` 类型,将核心类型体系扩展为四种。跨语言观察显示,Lua 将一维向量转置视为非法错误,NumPy、Mathematica 和 SciRuby 将转置作为恒等操作(v^T = v),R 和 MATLAB 则过度依赖矩阵提升。通过为 `RowVector` 针对 `transpose` 和 `*` 补充方法定义,Julia 借助多重分派化解了歧义。Chen 认为,这种方法虽使乘法方法表急剧膨胀,但它完全契合人类逐步学习乘法多态性的认知路径(从整数、分数、实数到复数及矩阵),最终实现了无需特异解析规则的高层数学表达自洽。 Chen 总结强调,语言设计者长期忽视了连接扁平向量与列矩阵所需的显式同构难度,以及乘法本质上的多态性。Andy Ferris 在代码实现上的落地证实了在基于类型的分派系统中,要完整、严谨地支持经典 Householder 记号,四种独立类型是不可或缺的最低要求。

Detailed notes — zh

## Background 该视频由 YouTube 频道 The Julia Programming Language 于 2017 年 7 月 17 日发布,内容为 Jiahao Chen 在 JuliaCon 2017 上的技术演讲。页面简介提供了 Julia 官方下载链接,并号召社区成员参与为视频添加时间戳与字幕以提高可发现性。 ## TL;DR 演讲围绕 Julia 社区争议极大的 GitHub Issue 4774 展开,深入剖析了语言在向量转置设计上的失误与反思。Jiahao Chen 梳理了线性代数演进史与 Householder 记号法则,指出列向量与扁平向量在数学定义上的细微割裂与同构困境。通过对比 MATLAB 的“万物皆矩阵”哲学以及各编程语言的处理方案,他证明了仅靠三种类型无法自洽支持 Householder 记号体系,并解释了 Julia 最终引入行向量(RowVector)及多重分派以完美实现类型闭合的底层逻辑。 ## Atmosphere & style 整场演讲兼具深厚的学术考据与风趣幽默的社区自嘲风格,现场互动热烈。演讲者以扎实的数学史文献为引,从坦承团队过去的认知错误切入,层层拆解看似平常的向量转置背后的深层代数矛盾。叙事条理清晰、抽丝剥茧,既有对语言架构复杂性的理性敬畏,也有致敬落地贡献者时的真挚温情,带给听众一种豁然开朗的智性享受。 ## Bulletin - [00:00](https://www.youtube.com/watch?v=C2RO34b_oPM&t=0s) Julia 社区著名的 GitHub Issue 4774 围绕“向量转置”引发了长期论战,类似争议在 NumPy 社区也曾产生多达 381 条讨论,暴露了科学计算语言在向量类型语义上的普遍痛点。 - [01:29](https://www.youtube.com/watch?v=C2RO34b_oPM&t=89s) 数学史上对向量存在“矩阵的一列(列向量)”与“向量空间元素(平坦向量)”两种自然同构但不等同的定义,这一历史分歧是现代数值计算类型冲突的根源。 - [13:43](https://www.youtube.com/watch?v=C2RO34b_oPM&t=823s) Jiahao Chen 证明仅凭标量、向量和矩阵三种基础类型,在严格类型系统中无法同时自然满足 Householder 记号下的内积、外积与双线性型运算。 - [13:43](https://www.youtube.com/watch?v=C2RO34b_oPM&t=823s) Julia 最终通过引入行向量(RowVector)构成四类型体系,并依托多重分派完整支持了 Householder 线性代数记号法则。 ## Key takeaways - [00:00](https://www.youtube.com/watch?v=C2RO34b_oPM&t=0s) GitHub Issue 4774(Taking vector transposes seriously)是 Julia 历史上争论最激烈的核心议题之一,涉及设计团队在向量认知上的多重偏差。 - [01:29](https://www.youtube.com/watch?v=C2RO34b_oPM&t=89s) 在 Julia 0.6 之前,内积计算返回单元素数组(1-element array)而非标量,导致复杂的数学公式频繁报错并严重破坏用户心智模型。 - [01:29](https://www.youtube.com/watch?v=C2RO34b_oPM&t=89s) “列向量”(二维矩阵的一列)与“平坦向量”(纯粹的抽象向量空间元素)虽然在数学上自然同构,但并不等同,混淆二者是语言设计陷入混乱的底层根源。 - [03:20](https://www.youtube.com/watch?v=C2RO34b_oPM&t=200s) 从 1920 年代到 1960 年代,线性代数经历了矩阵与向量各自独立、谨慎统一到现代完全视为理所当然的演变过程。 - [04:59](https://www.youtube.com/watch?v=C2RO34b_oPM&t=299s) 范德瓦尔登的《现代代数》与瑟斯通的《心灵的向量》等经典著作表明,从元组、向量到列矩阵的演化伴随着几何与代数视角的长期拉扯。 - [07:08](https://www.youtube.com/watch?v=C2RO34b_oPM&t=428s) Householder 记号通过小写字母代表向量、大写字母代表矩阵,用转置和相乘表达内积与外积,但在计算机底层依赖从向量到矩阵及 1×1 矩阵到纯量的隐式同构还原。 - [11:02](https://www.youtube.com/watch?v=C2RO34b_oPM&t=662s) MATLAB 之所以能规避部分冲突,是因为坚持“万物皆矩阵”哲学,并依赖“尾随单一维度规则”(trailing singleton dimension)按形状进行隐式动态转换。 - [11:02](https://www.youtube.com/watch?v=C2RO34b_oPM&t=662s) 针对类似 x'*y 的写法引入特殊解析规则会破坏运算符的自由组合性,用户多加一对括号就可能导致返回类型突变或计算报错。 - [13:43](https://www.youtube.com/watch?v=C2RO34b_oPM&t=823s) 在标量、向量、矩阵构成的 2×2 设计空间中,任何三类型体系在矩阵乘向量与转置输出的选择上都必须付出代价,内积、外积与双线性型三者不可兼得。 - [14:56](https://www.youtube.com/watch?v=C2RO34b_oPM&t=896s) 主流语言在此问题上各走极端:Lua 直接报错,NumPy 与 Mathematica 采用恒等变换,R 语言激进地全矩阵化,而 PARI/GP 与新版 Julia 则选择四类型显式体系。 - [16:19](https://www.youtube.com/watch?v=C2RO34b_oPM&t=979s) 引入 RowVector 后产生的大量乘法方法并非系统坏味道,乘法本身就是高度多态的泛型函数,这与人类从整数、有理数到复数和矩阵的数学认知进阶完全吻合。 - [17:48](https://www.youtube.com/watch?v=C2RO34b_oPM&t=1068s) 演讲总结指出在基于类型分派的语言系统中,至少需要四种基础类型才能完整且自洽地实现 Householder 记号。 ## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=C2RO34b_oPM&t=0s) 著名的 Issue 4774 与“向量转置”争端 演讲者 Jiahao Chen 开场介绍,他大约在四个月前离开了 MIT CSAIL 的 Julia 实验室,目前就职于纽约的 Capital One。但他特别声明,本次演讲的内容均是在加入 Capital One 之前完成的,因此前东家无法限制他对此话题的表达。随后,他向台下观众提到了 Julia 社区历史上极其著名且极具争议的 GitHub Issue 4774(标题为“Taking vector transposes seriously”,即“严肃对待向量转置”)。当他询问有多少人读过这个 Issue 时,现场大约四分之三的听众举起了手。 Jiahao Chen 直截了当地抛出核心结论:“The punch line here is that we were wrong on at least four counts on this issue and I will explain as much as possible within half an hour why we were wrong.”(“这里的关键在于,我们在该 Issue 上至少犯了四处错误,我会在半小时内尽量解释我们到底错在哪里。”)他提到,Issue 4774 堪称社区有史以来争论最激烈的议题之一,他在社区几位泰斗级人物之间做了意见征集,发现大家的看法大相径庭,甚至有人因意见冲突未能到场。而且这个问题并非 Julia 独有,Python 社区(NumPy)同样曾就类似问题产生过多达 381 条讨论评论,说明这在科学计算语言领域是一个极其容易激起情绪的经典难题。 - **GitHub Issue 4774**:“Taking vector transposes seriously”,Julia 语言设计史上讨论最激烈的核心争议之一。 - **跨社区共鸣**:Python / NumPy 社区也在向量表示与转置问题上有过多达 381 条讨论的争议记录。 --- ### [01:29](https://www.youtube.com/watch?v=C2RO34b_oPM&t=89s) 用户痛点与“什么是向量”的数学分歧 在展示 Julia 0.6 的表面问题时,Jiahao Chen 贴出了一张在 Google 上搜索“mathematician(数学家)”排在第一位的经典爱因斯坦吐舌照作为用户代表。在 Julia 0.6 之前的版本中,当数学家或普通用户输入内积等常规算式时,得到的不是纯量(标量),而是一个单元素数组(1-element array);当用户尝试进一步书写更复杂的数学表达式时,Julia 就会直接抛出一长串错误,导致用户极度郁闷并质问:“Don't you Julia people know any mathematics at the bottom?”(“你们这帮搞 Julia 的人难道一点数学都不懂吗?”)针对开发团队曾经“为什么一定要这么写内积”的困惑,Jiahao Chen 进行了深入研究,得出了一个根本性结论:大家其实并不真正清楚“向量(Vector)”到底是什么。 ```mermaid flowchart TD accTitle: 向量的两种数学定义分歧 accDescr: 对比列向量与平坦向量在结构和空间代数上的差异 subgraph Def1["定义一:列向量 (Column Vector)"] A["矩阵的一列 (Column of a Matrix)"] A --> B["天然属于二维矩阵范畴"] A --> C["具备向量空间代数性质"] end subgraph Def2["定义二:平坦向量 (Flat Vector)"] D["纯粹的向量空间元素 (Element of Vector Space)"] D --> E["具备向量空间代数公理"] D --> F["并不必然是矩阵的一列"] end Def1 -.->|"自然同构但并不等同 (Isomorphic but not identical)"| Def2 ``` Jiahao Chen 阐明,在数学内部对“向量”其实存在着两种略微不兼容的定义: 1. **定义一(列向量,Column Vector)**:向量是矩阵的一列。 2. **定义二(平坦向量,Flat Vector)**:向量是具备向量空间代数性质的对象。 这两种向量“naturally isomorphic but not identical”(“自然同构,但并不等同”)。第一类列向量显然拥有向量空间的代数性质,但并非所有满足向量空间公理的向量都属于矩阵的一列。整场争端的根源,实际上就在于语言设计中混淆了这两种概念。 --- ### [03:20](https://www.youtube.com/watch?v=C2RO34b_oPM&t=200s) 线性代数的演进历史:从彼此割裂到 emoji 三阶段 为了厘清为什么会出现这两种互不兼容的定义,Jiahao Chen 梳理了线性代数的历史脉络。在大约 1924 年至 1960 年之前,历史上对矩阵和向量的处理曾经历过一次重大分野。曾经存在一个矩阵与向量完全彼此独立的时代:矩阵自成一派,向量也自成一派,二者毫无交集;直到某个历史节点,这两门学科才走向合并,而现代人正是生活在合并之后的宇宙中。 在矩阵独立宇宙中,存在的是“列矩阵(Column Matrix)”这种称谓以及现代线性代数常见的记号体系;而在向量宇宙中,发展的则是向量空间公理、坐标几何以及元组(Tuple)概念。到了 1920 年代,数学家们终于意识到“列矩阵构成了向量空间”,这才诞生了后来的混合定义。Jiahao Chen 用三个表情符号(Emoji)生动地概括了这段历史演进的三个阶段: 1. **统一前时代(Pre-unification Era)**:矩阵与向量各自独立。 2. **统一初期(Early Unification Era)**:学者在著书立说时,必须极度小心严谨地区分并解释两者为何可以联系起来。 3. **完全统一时代(Post-unification Era)**:两者被视为理所当然的同一概念,甚至变成了“大家在小学就应该学会”的常识。 --- ### [04:59](https://www.youtube.com/watch?v=C2RO34b_oPM&t=299s) 经典教材中的定义溯源:从范德瓦尔登到 1935 年的统计学 Jiahao Chen 翻阅了现代抽象代数的奠基之作——范德瓦尔登(van der Waerden)的《现代代数》(*Modern Algebra*)。在这本开创现代代数体系的著作英文译本中(其用词体系从第一版德文版完整继承下来): - **向量(Vector)**:是拥有代数运算的抽象对象。 - **系数(Coefficients / Ring Elements)**:构成元组(Tuple),作为纯量(标量)存在。 - **元组(Tuple)**:是可按索引访问的系数集合,但其自身并没有定义代数运算。 - **列矩阵(Column Matrix)**:则是借由更早的线性代数主题为该向量所赋予的具体形式。 随后,他又引用了 1935 年由 L. L. Thurstone 所著的极具特色的统计学专著《心灵的向量:分离主要特质的多因子分析》(*The Vectors of Mind: Multiple Factor Analysis for the Isolation of Primary Traits*)。书中写道:如果一个矩阵只有单列,它就是列向量;如果只有单行,它就是行向量;而这种向量化的术语命名,本质上可以被视为几何学引入的产物。Jiahao Chen 强调,这一段论述精准道出了从分裂宇宙向统一宇宙过渡的关键症结。 --- ### [07:08](https://www.youtube.com/watch?v=C2RO34b_oPM&t=428s) Householder 记号法则与内积同构的实现断层 时间推进到 1953 年数值分析(Numerical Analysis)作为一门学科诞生的时刻,阿尔斯通·豪斯霍尔德(Alston Householder)提出的 Householder 记号法成为了现代数值分析学家书写矩阵代数的行业基石与通用语言: - **纯量(Scalar)**:使用小写希腊字母(如 $\alpha, \beta$)。 - **向量(Vector)**:使用小写罗马字母(如 $u, v$)。 - **矩阵(Matrix)**:使用大写罗马字母(如 $A, B$)。 在这种约定下,复杂的矩阵和向量计算本质上只是三种基本乘积的复合:内积写作 $u' v$(转置乘向量),外积写作 $u v'$,双线性型(Bilinear Form)写作 $u' A v$。要表达所有这些运算,理论上只需要“转置(Transpose)”与“相乘(Multiplication)”两个基本操作。然而,这其中隐藏着一个计算机科学视角的暗坑:要使 $u' v$ 成立并直接返回一个标量,底层其实依赖了隐式同构转换。 ```mermaid flowchart LR accTitle: Householder 记号中的隐式类型转换链路 accDescr: 解释向量与矩阵、1x1 矩阵与标量之间的转换过程 subgraph Left["输入转换 (Isomorphism 1)"] V["向量 (Vector)"] -->|"提升/同构"| CM["列矩阵 (Column Matrix)"] end subgraph Calc["标准矩阵代数核心"] CM -->|"矩阵转置 '"| RM["行矩阵 (Row Matrix)"] RM -->|"矩阵乘法 *"| M11["1×1 矩阵"] end subgraph Right["输出转换 (Isomorphism 2)"] M11 -->|"同构还原"| S["纯标量 (Scalar)"] end ``` Jiahao Chen 分析指出,如果完全按照矩阵相乘规则,左侧需要将向量提升(Promote)为列矩阵,进行矩阵转置得到行矩阵,再与右侧的列矩阵相乘得到 $1 \times 1$ 的矩阵,最后右侧还必须存在一个将 $1 \times 1$ 矩阵还原为纯标量(数域上的系数)的同构过程。问题的关键就在于:“whether or not you want your language to deal with these isomorphisms for you or whether you want to deal with them yourself”(“你究竟是希望编程语言在底层替你处理好这些同构映射,还是希望由你自己手动来应付它们”)。 在 Julia 0.5 及更早版本中,转置操作的实现机制正是因为这种逻辑而彻底崩塌:当用户调用向量转置时,系统将向量提升为矩阵,转置为行矩阵,再执行矩阵乘向量运算,结果必须返回一个向量(1-element Vector)。由于在代数体系中不能对向量做除法,单元素向量不具备标量代数特性(无法像 $1 \times 1$ 矩阵那样直接参与纯量加减乘除),导致诸如 $u' v$ 之后进行后续代数运算的代码全面报错,最终留下了沮丧的用户。而对于像 MATLAB 这种历史悠久的工具,Jiahao Chen 直言,它在现代编程语言中其实是一个异类(Anomaly),这也正是许多习惯了通用语言类型的开发者在面对矩阵导向逻辑时感到无所适从的根源。 ### [11:02](https://www.youtube.com/watch?v=C2RO34b_oPM&t=662s) MATLAB 的设计哲学与“尾随单一维度”规则 Jiahao Chen 深入分析了 MATLAB 这一数值计算领域的先驱为何能够规避向量转置的许多类型矛盾。MATLAB 的底层语义完全建立在第一类向量(Type 1 Vectors,即列向量)的基础之上。陈嘉豪引用了两段极具代表性的官方文献来佐证这一点:第一段出自 Cleve Moler 仍在新墨西哥大学任教时于 1980 年撰写的原始《矩阵实验室》(Matrix Laboratory)技术报告,其中明确写道:“在 MATLAB 中,矩阵是唯一的数据类型,标量、向量和文本都只是其特例。”;第二段则摘自 2016 年的 MATLAB 官方手册,其定义依然保持着惊人的一致性:“一侧维度等于 1、另一侧维度大于 1 的矩阵被称为向量。” MATLAB 之所以没有遭遇复杂的语义死锁,是因为其系统中“万物皆矩阵”(Everything is a matrix),所有的标量和向量都会根据上下文需求被动态隐式强制转换(coerced on demand)。这种机制在工程实现上被称为“尾随单一维度规则”(trailing singleton dimension rule)——系统允许在数组末尾随意添加或去除长度为 1 的维度。在此框架下,原本复杂的数学同构被简化为了根据需要添加或丢弃末尾索引的操作。更重要的是,在 MATLAB 中计算出 $1 \times 1$ 的矩阵后即可直接终止,无需显式将其转换为真正的机器标量,这足以应付大部分数值运算。 ```mermaid flowchart TD accTitle: MATLAB Matrix-Only Paradigm accDescr: 阐释 MATLAB 中将所有数据结构视作矩阵并通过尾随单一维度规则进行隐式处理的流转机制。 subgraph MATLABModel ["MATLAB 的统一矩阵模型"] M["核心数据类型:矩阵 Matrix (n × m)"] V["向量特例:(1 × n) 或 (n × 1)"] S["标量特例:(1 × 1) 矩阵"] end M -->|"尾随单一维度规则 (Trailing Singleton Dimension)"| V V -->|"计算自然保留,无需强转真标量"| S S -->|"基于形状重载 * 乘法规则"| R["直接输出结果 (优雅但违背类型分派)"] ``` 然而,陈嘉豪指出这种优雅只是一种表象,对于依赖严格类型分派(type dispatch)的现代语言(如 Julia)而言,它并不适用: - 为了让 $1 \times 1$ 矩阵表现得像标量,底层乘法运算必须根据数组形状(shape-based)编写极其繁琐的特例分支,左乘 $1 \times 1$ 矩阵和右乘 $1 \times 1$ 矩阵都需要单独处理。 - 语言如果单纯依赖转置和乘法来实现 Householder 记号,要么必须极度精细地定义这两个算子,要么就必须引入复杂的特殊解析规则(special parsing rules)。 - 这种解析规则实际上是将类似于 `x'*y` 的语法变成了独立的特殊算子,这彻底破坏了算子的组合性(breaks composition)。用户一旦不小心在表达式中多加了一对括号,就会导致类型完全改变,甚至引发无法预料的错误。 - 正如陈嘉豪所引述的观点:“正如 Jeff(Bezanson)等人肯定会告诉你的那样,它们给语言增加了复杂性,而且这是为了一个极其特殊的目的而增加的复杂性,这样做显得有些奇怪。” --- ### [13:43](https://www.youtube.com/watch?v=C2RO34b_oPM&t=823s) 2×2 设计空间与行向量(RowVector)的引入 在剖析了三类型系统(仅包含标量、向量、矩阵)的局限性后,陈嘉豪给出了一个精练的 $2 \times 2$ 语言设计空间矩阵。如果一门语言只保留这三种基础类型,在定义矩阵乘向量 $A \cdot b$ 的输出(是向量还是列矩阵)以及向量转置 $b'$ 的输出(是行矩阵还是自身)时,设计者必然陷入两难: | 设计维度 | $b'$ 返回自身(Identity / Flat Vector) | $b'$ 返回行矩阵(Row Matrix / Type 1) | |:--- |:--- |:--- | | **$A \cdot b$ 返回一维向量(Vector)** | 内积计算错误(旧版 Julia 所处的象限) | 二次型与双线性型破坏(Bilinear Forms 失败) | | **$A \cdot b$ 返回列矩阵(Column Matrix)** | 外积计算错误(Outer Product 失败) | 失去扁平向量概念,退化为全矩阵体系 | 陈嘉豪直言,无论在 $2 \times 2$ 的四个象限中如何选择,都无法在仅有三种类型的体系下完美实现 Householder 记号:“这就是我们的核心结论:三者不可兼得。” 旧版 Julia 牺牲了内积的自然性,而其他象限则会破坏外积或双线性型。为了走出这一死局,Julia 社区最终引入了第 4 个核心概念——行向量(`RowVector`)。结合 Julia 标志性的多重分派机制,四类型体系终于彻底理顺了所有的线性代数运算。陈嘉豪总结道:“这个故事的寓意是:你无法仅用三种类型满足 Householder 记号的要求,但有了四种类型,你就可以做到。” --- ### [14:56](https://www.youtube.com/watch?v=C2RO34b_oPM&t=896s) 各主流语言在向量转置上的横向图景 陈嘉豪展示了一张信息量巨大的全景对比图,系统梳理了各大计算语言在向量转置问题上的不同技术路线: - **报错抛出异常(Error)**:例如 Lua,对一维向量执行转置会直接抛出运行时错误。 - **恒等变换(Identity)**:NumPy(Python)、Mathematica 以及 SciRuby 采取此方案,即一维向量的转置依然是自身。 - **全矩阵化策略(All-Matrix)**:以 R 语言为代表。R 的设计极为激进且容易理解——只要调用了矩阵乘法运算符 `%*%` 或转置函数 `t()`,返回结果瞬间变成二维矩阵。虽然概念简单,但代价是彻底丢失了向量的语义。 - **四类型显式转换系统**:除了新版 Julia 之外,计算机数论计算专业语言 PARI/GP 也位于这个象限。在 PARI/GP 中,列向量、行向量、行矩阵和列矩阵之间不仅类型泾渭分明,而且需要显式调用函数进行相互转换。 - **未探索象限(Unexplored)**:设计空间中仍有少数空白组合无人涉足,陈嘉豪风趣地向听众建议:“如果你对设计自己的编程语言感兴趣,或许可以亲自尝试一下这些未被开发的方案,看看体验到底如何。” --- ### [16:19](https://www.youtube.com/watch?v=C2RO34b_oPM&t=979s) 多态分派与人类数学认知的自然映射 针对部分开发者对“引入 `RowVector` 导致系统必须增加大量乘法与转置方法定义”的担忧,陈嘉豪展示了 Julia 内部乘法方法列表的幻灯片。幻灯片上密密麻麻地排满了代码,为了塞下所有定义,“从第一条方法定义往后,字号全部调成了 1.5 磅”。 陈嘉豪认为这种方法的膨胀非但不是设计缺陷,反而是非常自然的进化。因为在 Julia 中,乘法本质上就是一个高度多态的泛型函数(highly polymorphic generic function),这种多重分派系统与人类学习数学的心智模型高度吻合: 1. 启蒙阶段:每个人都是从乘法表开始的,即简单的整数乘法(`Int * Int`); 2. 学校进阶:接触到分数,引入了有理数与整数的混合运算(`Rational * Int`); 3. 连续数学:学习实数和小数,掌握了实数乘法(`Real * Real`); 4. 高等数学:在大学阶段逐步扩展至复数乘法(`Complex * Complex`)以及矩阵与向量的相乘(`Matrix * Vector`)。 因此,向系统引入 `RowVector * Matrix` 或 `RowVector * Vector`,只是数学学习路径的自然延续,“仅仅是沿着同样的逻辑继续前行罢了”。 --- ### [17:48](https://www.youtube.com/watch?v=C2RO34b_oPM&t=1068s) 总结致谢与对向量认知的深刻反思 在演讲尾声,陈嘉豪总结了整个重构历程带给团队的深刻教训,并郑重向核心贡献者致敬。他特别邀请坐在台下的 Andy Ferris 起立接受全场掌声,并赞誉道:“作为一名学者,我的特权只是在这里空谈理论,推演该怎么做;但 Andy 则是那个真正挽起袖子把代码实现出来的人。” 陈嘉豪在结语中呼吁社区重新审视那些被习惯所掩盖的底层认知: - 整个技术社区过去在向量的认知上长期存在盲区,“我们全都弄错了向量的本质,并且忘却了过去那些真正困难的问题”。 - 开发者习惯性地忽略了列矩阵、行矩阵与一维扁平向量之间的数学同构在计算机底层所带来的阻抗。 - 乘法在本质上就是一个被高度重载的多态运算,试图用简单的单一规则覆盖它是不切实际的。 - 本次探索最重要的理论沉淀在于:“你至少需要四种类型,才能在基于类型分派的系统中完整实现 Householder 记号。” 这一结论为 Julia 生态长期以来关于向量、转置与维度的激烈争论画上了清晰的理论句号。 ## Notable quotes > [17:48](https://www.youtube.com/watch?v=C2RO34b_oPM&t=1068s) 你至少需要四种类型,才能在基于类型分派的系统中完整实现 Householder 记号。 — Jiahao Chen > [11:02](https://www.youtube.com/watch?v=C2RO34b_oPM&t=662s) 在 MATLAB 中,矩阵是唯一的数据类型,标量、向量和文本都只是其特例。 — Cleve Moler ## Mentioned Jiahao Chen, Capital One, MIT CSAIL, Julia, NumPy, Python, B. L. van der Waerden, L. L. Thurstone, Alston Householder, Cleve Moler, MATLAB, Jeff Bezanson, Andy Ferris, Lua, Mathematica, SciRuby, R, PARI/GP ## Video description Visit http://julialang.org/ to download Julia. Time Stamps: 00:00 Welcome! 00:10 Help us add time stamps or captions to this video! See the description for details. Want to help add timestamps to our YouTube videos to help with discoverability? Find out more here: https://github.com/JuliaCommunity/YouTubeVideoTimestamps Interested in improving the auto generated captions? Get involved here: https://github.com/JuliaCommunity/YouTubeVideoSubtitles [Source](https://www.youtube.com/watch?v=C2RO34b_oPM)

Source quotes

[17:48] Jiahao Chen: 你至少需要四种类型,才能在基于类型分派的系统中完整实现 Householder 记号。 [11:02] Cleve Moler: 在 MATLAB 中,矩阵是唯一的数据类型,标量、向量和文本都只是其特例。

Source quotes

[11:02] Cleve Moler: In MATLAB, the matrix is the only data type, with scalars, vectors, and text as special cases.

Original transcript

[0:00] my name is Jal Chan U until about four [0:03] months ago I was at mitc cell uh with [0:06] the Julia Labs uh I currently work at [0:08] Capital One in New York uh but the [0:10] disclaimer here is that this is all work [0:12] that was done before I went to Capital [0:14] One so they don't get to tell me what I [0:16] can't say about this topic so some of [0:20] you may remember this issue taking back [0:22] the transposer seriously how many of you [0:24] how many of you have read this issue oh [0:26] my goodness okay all right three qus of [0:29] you guys rais your hands okay so I the [0:32] punch line here is that we were wrong on [0:34] at least four counts on this issue and I [0:36] will explain as much as possible within [0:39] half an hour why we were wrong um as you [0:42] know 4774 is quite possibly one of the [0:45] most hotly debated issues of our time [0:47] and I went to sample some luminaries of [0:50] our community to ask about their [0:52] opinions so here's [0:56] one oh sorry thank you uh so here's one [0:59] opinion [1:00] here's another opinion from another [1:02] luminary and here's yet another uh [1:05] opinion from that another luminary uh [1:08] who unfortunately could not be here and [1:10] thus was born this [1:12] issue uh surprisingly it's not just us [1:15] so uh turns out that the python people [1:18] had also thought about this and they had [1:20] what is it 381 comments on this [1:23] particular issue so this seems to be [1:25] something that gets people riled up a [1:27] lot so let me introduce the surface [1:29] problem this is what Julia 0.6 looks [1:32] like so here I Googled the first image [1:35] for mathematician and that is what I got [1:38] so I'm using I'm using that so user [1:41] comes in and says I can't compute with [1:43] Julia I typed this and it gave me a one [1:47] element array and then I tried to put in [1:49] a more complicated expression which I [1:51] want to type and it says blah blah blah [1:53] blah error sad I am [1:57] unhappy don't you know any mathematics [2:00] oh it's little cut off huh it says don't [2:02] you Julia people know any mathematics at [2:04] the at the [2:05] bottom um our response here is why would [2:08] you want to do that okay why do people [2:10] want to write in a products like this [2:12] and why do people get so worked up about [2:14] this issue uh so I did some [2:18] research and I've come to a conclusion [2:21] that people don't know what vectors [2:23] are this issue exists because there are [2:26] two slightly incompatible meanings of [2:28] the word Vector in mathematics [2:33] here are the two definitions a vector is [2:35] a column of a [2:36] matrix second definition a vector is [2:39] that which has the algebra of a vector [2:41] space Not Meant To Be fatuous toy [2:46] naturally isomorphic but not identical [2:48] these two vectors are similar but not [2:50] identical so a type one vector a column [2:54] of Matrix clearly has the algebra of a [2:57] vector space however not all vectors [3:00] which have the algebra of a vector space [3:02] are columns or matrices on some level [3:05] this issue really is that simple um and [3:07] I will refer to these two vectors as [3:09] column vectors and flat vectors for the [3:13] rest of this talk um I will be careful [3:16] where possible to distinguish between [3:17] these two users of [3:20] vector you might ask why did we end up [3:22] with two definitions of vector anyway [3:25] and it turns out I read I read some [3:27] books and it turns out that this is what [3:29] the history of linear algebra looks like [3:31] U and this is as as simple as I've been [3:33] able to make it uh in short sometime [3:37] around 1924 to 1960 there was a division [3:42] in the historical treatment of matrices [3:44] and vectors there was once a universe [3:46] where matrices were their own subject [3:48] and vectors were their own subject and [3:50] these two subjects did not mix [3:52] whatsoever and at some point they merged [3:55] and and we work in the world of the the [3:58] post merger uh un inverse of matrices [4:00] and [4:02] vectors just some just some key moments [4:04] in the history here so we see that on [4:07] the left hand side the Matrix only [4:09] Universe uh we have things like the [4:11] phrases like column Matrix we have the [4:14] notation that many of us recognize today [4:16] when we do linear algebra uh on the [4:18] vector side we have the vector space [4:21] axioms we have the coordinate geometry [4:23] uh we have the notion of tupo and at [4:26] some point uh in the 1920s the [4:28] mathematicians said said oh hey column [4:31] matrices form a vector space and hence [4:33] was born the other definition which is [4:36] both older and newer than the other [4:39] definition so if this is too complicated [4:42] I have tried to retell the story with [4:44] Emoji there's a pre-unification [4:46] era there is the early unification era [4:49] where you needed to explain this [4:50] carefully and then there's the era where [4:52] it's also obvious you should have [4:53] learned this in elementary [4:56] school so what does this look like so I [4:59] P I pulled out one of these books and V [5:01] ven's uh book on Modern algebra is [5:03] arguably the textbook that invented [5:06] abstract algebra in its modern form and [5:09] what did he write about this uh you will [5:11] notice first of all that this is all not [5:13] in German uh it's in English but [5:15] nonetheless you can uh I have it on good [5:17] authority that this survives from the [5:19] first edition of the modern algebra [5:21] textbook that this is how he named all [5:25] the things so vectors were the abstract [5:27] thing that had the algebra [5:30] and it is composed of [5:32] coefficients and the coefficients [5:34] themselves form tup and by the way you [5:37] can assign to this Vector a column [5:40] Matrix so to recap the algebra is in the [5:43] vector the coefficients which what we [5:46] may today call ring elements um are just [5:49] some numbers some scalers these these [5:52] are the things that define scalers t are [5:54] indexable collections of these [5:56] coefficients these elements of a ring uh [5:59] but but there's no algebra defined on [6:00] them and then by the way there's this [6:02] older topic called linear algebra that [6:05] uh that has column [6:06] Matrix um warning again most of these [6:10] words are horribly horribly [6:12] overloaded uh but I think this this [6:14] maybe gives you a sense of what [6:16] mathematicians were thinking about when [6:17] they talked about algebra and vectors [6:19] and in the context of vector [6:23] spaces I another book that I thought was [6:25] really enlightening about this era uh [6:28] comes from this book which has this [6:30] awesome title called the vectors of [6:32] Mind multiple factor analysis for the [6:35] isolation of primary traits so this is [6:37] actually a statistics textbook uh from [6:39] 1935 and I think it explains very [6:42] clearly how this Evolution made a [6:44] transition from the isolated Universe to [6:47] the post-unification [6:48] universe so I will I'll read a little [6:50] bit of this uh basically that if a [6:53] matrix has a single column it is a [6:55] column Vector if it has a single row it [6:57] is a row vector and the vectorial [6:59] terminology probably can be regarded as [7:02] a consequence of [7:04] geometry so I think this is this is [7:06] really really the Crux of the [7:08] matter fast forward to 1953 when the uh [7:12] field of numerical analysis was invented [7:15] and this is the language and Cornerstone [7:18] of how all numerical analysts today [7:21] speak Matrix [7:22] algebra so most of you most of you here [7:25] may not be familiar with householder [7:27] notation so I will just summarize this [7:30] very briefly uh essentially there is a [7:32] typographic convention where scalers are [7:35] small Greek letters uh vectors are small [7:37] Roman letters and matrices are large [7:40] Roman letters and you want to spell [7:42] certain things as as follows for example [7:45] you might want a inner product which you [7:47] want to write as U Prime * V an outer [7:50] product that's U * V Prime and then you [7:52] have uh bilinear forms that look like U [7:54] Prime * a * v u and I would argue that [7:57] just about every complicated expression [8:00] involving matrices and vectors really [8:02] come down to compositions of these [8:04] Elementary types of products now the [8:06] interesting thing here is that you only [8:08] need two operations to express all of [8:10] them you only need the transpose and the [8:13] multiplication okay and there a there's [8:16] a caveat here uh oh excuse me let me try [8:19] that [8:27] again okay sorry about that uh so the [8:30] caveat here is what exactly we mean by [8:32] transpose and [8:33] multiply uh so so let's let's dig into [8:36] one of these things it turns out that [8:39] there is an assumption here about Matrix [8:40] algebra that is hidden in the desire to [8:44] write something like U Prime * V being a [8:47] product involving vectors and vectors [8:49] returning a scalar so I've tried to [8:51] break it down uh in in the way a [8:53] computer scientists might and try to [8:55] assign the meanings of various arrows [8:57] here so you see that what you do here is [8:59] first of all you convert everything to [9:01] matrices and then the regular [9:04] definitions of Matrix transpose and [9:06] Matrix multiply automatically hold you [9:08] don't need new definitions of what prime [9:10] and star are in this case so long as you [9:13] are able to automatically convert [9:15] between vectors and column matrices on [9:17] the left hand side and on the right hand [9:19] side a conversion between 1 by one [9:22] matrices and true scalers which are [9:24] these coefficients of the field so [9:27] what's really missing here from this [9:28] picture which I will highlight [9:30] explicitly are these isomorphisms and [9:33] this exp this is really it comes down to [9:36] the Crux really of whether or not you [9:38] want your language to deal with these [9:40] isomorphisms for you or whether you want [9:42] to deal with them yourself all right [9:45] that's the second version of the punch [9:46] line Julia prior to 0.6 um actually used [9:51] this particular definition so in the [9:53] context of an inner product what we said [9:56] was the promotion from Vector to Matrix [9:58] and Matrix trans transpose is our [10:00] definition of what a vector transpose is [10:04] and the thing that that uh results from [10:07] this is that if you think about this [10:10] expression as the composition of just [10:11] transpose and multiply that it's [10:14] actually broken and it's broken in a [10:16] very bad way because this is what [10:18] happens inside in uh Julia 0.5 and [10:21] earlier that you promote the V the left [10:24] hand side Vector to a matrix then apply [10:25] a transposition to get a row Matrix and [10:28] then you have a matrix vector product [10:29] which of course must return you a vector [10:32] and vectors are bad because you cannot [10:34] divide by them they don't have a scalar [10:35] algebra for example that one by one [10:38] matrices are actually much better at you [10:40] can do scaler operations with one by one [10:42] matrices and you just can't do very much [10:44] with one vectors and the result is [10:47] unhappy [10:48] Einstein so this other competing [10:51] language that you may have heard about [10:53] Matlab uh it is I will argue that mlab [10:57] uh is an an normally modern languages [11:00] and it's why we feel uncomfortable about [11:02] some of it semantics and it's because [11:04] it's firmly rooted in type one vectors [11:06] which are columns um so two quotes from [11:09] uh various documentation about Matlab [11:12] the first one comes from the original [11:13] Matrix laboratory report from 1980 from [11:16] the University of New Mexico when CLE M [11:19] was still faculty there in matlb The [11:21] Matrix is the only data type with [11:24] scalers vectors and text as special [11:26] cases the second one comes from last [11:28] year's m manual where it still says [11:31] matrices with Dimension equal to one on [11:33] one side and greater than one on the [11:35] other side are called vectors so now [11:38] that we are primed to see that there are [11:40] two definitions of vector this is very [11:42] clearly a type one vector that is being [11:44] defined in matlb so why doesn't matlb [11:47] have this problem it's because [11:49] everything is a matrix and everything is [11:51] coerced on demand to vector or Scala as [11:53] necessary and uh some of you may know [11:56] this as the trailing Singleton Dimension [11:58] rule where you can arbitrarily add or [12:01] remove uh uh extra Dimensions that have [12:05] just length one at the end of a uh array [12:08] in in mat lab so what you see here is [12:11] that our isomorphism simply become the [12:14] addition and dropping of uh of trailing [12:17] indices as necessary and furthermore in [12:20] in mat lab you just stop at the 1ex one [12:22] Matrix expression you don't need to [12:23] convert it to a true scaler because [12:25] that's good enough uh and and and so [12:29] this this actually is a fairly elegant [12:31] solution to the type one vector [12:33] implementation uh why is this bad it's [12:36] not necessarily bad but it's not really [12:39] u in line with how we think about [12:40] dispatch because now you have to add [12:43] these definitions to multiply that are [12:46] shape based so you have to special case [12:48] one by one matrices on the left and one [12:50] by one matrices on the right in order to [12:52] get this to work the way you want it [12:54] to so to summarize language design [12:57] considerations uh if you want to rely on [13:01] just transpose and multiplication to [13:02] write these Expressions you probably [13:04] have to Define transpose and multiply [13:06] very carefully and otherwise you [13:08] probably need special special passing [13:10] rules just to make this happen [13:12] effectively you're making something like [13:14] blank St blank Prime Star blank is [13:17] really its own special operator and this [13:19] breaks composition uh which may be very [13:22] very bad if you think about accidentally [13:24] introducing parentheses in the wrong [13:25] place you may get the wrong type as the [13:27] result and these kinds of so special [13:29] passing rules as uh people like Jeff I'm [13:32] sure will tell you they add complexity [13:33] to a language and this is complexity for [13:35] a very specific specific purpose and it [13:38] seems a little odd to do [13:40] this so what is the design space here [13:43] and it turns out that they're really [13:44] only these 2 x two choices if you only [13:47] have scalers matrices and vectors in [13:49] your language then these are the these [13:51] are the 2 by two uh Matrix as it were of [13:54] the design choices you can either have a [13:57] * B which gives you a vector [13:59] or a column Matrix on on the on the on [14:02] the one end and on the other hand you [14:04] can Define uh the transpose of a vector [14:07] to return you a row Matrix or just [14:10] itself and um so this is what you get [14:13] wrong if you want to insist on [14:15] implementing householder notation that [14:17] in some quadrants you get in a product [14:19] wrong which uh which is Us in uh in Old [14:21] Julia um in another quadrant you get [14:23] outter product wrong and the quadratic [14:25] products and bilinear forms are wrong on [14:27] the other side so so that's our that's [14:30] our uh main result here that you can't [14:33] have what you [14:35] want th was introduced the row vector [14:37] and it turns out that having a row [14:39] Vector uh combined with the type based [14:41] dispatch that we know have grown to love [14:44] in Julia actually can get everything to [14:46] work so the mor of the story is that you [14:48] can't get what you want for householder [14:50] with three types but you can with [14:53] four so what did everyone else do and [14:56] this is a really interesting uh uh slide [14:59] I think I've gone through and looked at [15:01] what other people do in this case uh you [15:04] can see that there's a wide variety of [15:05] things you might do to Vector transpose [15:07] either it's an error like in Lu um it [15:10] can be the identity like in napai in [15:13] Mathematica and also in s Ruby uh we [15:16] have the old Julia behavior on one hand [15:19] and we also have the the new Julia [15:21] behavior in yet another box and it turns [15:23] out that we're not alone in this box [15:24] there is this other language called par [15:27] GP which is used in number the [15:29] calculations which actually has this [15:31] design and furthermore you have to [15:33] explicitly convert between columns and [15:35] matrices and rows and matrices and rows [15:37] and columns uh on the other hand there's [15:40] R and R is actually a really interesting [15:43] uh design uh quadrant here because [15:46] basically as long the moment you do any [15:48] linear algebra the result is a matrix so [15:51] on some level this is actually really [15:53] easy to understand because so once you [15:55] invoke The Matrix multiply operator or [15:57] the transpose operator you get a matrix [16:00] and you know arguably matlb sort of fits [16:02] in this corner but not really since [16:04] we've already discussed that matlb does [16:06] not have true scalers or or vectors and [16:08] then there are these little pieces here [16:10] that nobody's explored and maybe this is [16:12] an Avenue for new language design so if [16:15] if you were interested in making your [16:16] own language you might want to try these [16:17] these out for yourself to see how you [16:19] like [16:19] them so how do row vectors work we need [16:23] new definitions of transpose and [16:25] multiply but then the actual Expressions [16:27] that you get is simpler because all you [16:29] do is just apply those two new [16:30] definitions and then you're done so the [16:34] question is is this really that bad that [16:35] we need more definitions probably not [16:38] because as you know multiplication is [16:41] already highly polymorphic in Julia uh [16:45] just for the record um everything past [16:47] the first method definition is font size [16:49] 1.5 right that's that's how many methods [16:52] we have in Julia but in some sense this [16:55] is a very natural uh uh there's a very [16:58] natural analogy between how Julia [17:00] organizes this kind of generic function [17:03] system and how we learn how to do [17:05] mathematics so I don't think anyone [17:08] really learned U multiplication from [17:11] complex numbers I think all of us [17:13] started from multiplication tables which [17:15] is int times int then maybe you graduate [17:17] in school to go to fractions and so you [17:20] have rational times int and then maybe [17:21] you have real numbers and decimos then [17:23] you have real time real then if you if [17:25] you stay in school long enough to learn [17:26] more mathematics you learn complex times [17:28] complex Matrix time vector and all this [17:30] other fun stuff so really just [17:33] introducing new things like row Vector [17:34] time Matrix row Vector time column [17:36] Vector it's just more of the same um so [17:39] that's that's a little bit of a handwavy [17:41] justification for why this is not such a [17:43] bad [17:44] design so the current [17:48] uh yeah so excuse me we don't really [17:51] need the slide uh instead I will skip [17:53] forward to just the summary and I'll [17:54] leave plenty of time for questions I'm [17:56] sure you have many first of all I think [17:58] we have taken vector the transposer [17:59] seriously at this point uh [18:02] [Applause] [18:08] oh and and really special credit really [18:11] has to go to Andy Ferris who is here [18:13] somewhere right who where are you please [18:16] give this man a one [18:17] [Applause] [18:20] hand as as you know it's my it was my [18:22] privilege as an academic to just [18:24] speculate about what to do but Andy [18:26] actually did it so that also deserves [18:28] plenty of credit [18:30] so really what I've learned from this is [18:32] that we were all wrong about vectors and [18:34] we have forgotten what used to be [18:37] difficult we've forgotten that we used [18:40] to have to worry about these [18:41] isomorphisms explicitly uh we have this [18:45] incompatible definitions of columns uh [18:48] of column vectors and flat vectors uh [18:50] We've forgotten that multiplication is [18:52] actually this inherently overloaded and [18:54] polymorphic operation and uh like our [18:56] one new result here is that you need at [18:58] least four types to do householder [19:00] notation in a type uh based dispatch [19:02] system and I will leave it at here and [19:05] take any questions you may have thank [19:08] you very much [19:11] [Applause]