To everyone arguing against special-casing matrix multiplication, please base your arguments on the PEP's "Motivation" section to avoid too much of rehashing the obvious. It even has a subsection "But isn't matrix multiplication a pretty niche requirement?"
This is surprisingly detailed design rationale which weighs many alternatives and gives careful consideration to possible tradeoffs. Great job by Nathaniel Smith and the numerical Python community.
The nice thing is that it makes a nice symbol `@` available to objects that aren't matrices, to do with as they want ...<p>The (ab)use seems endless :)
Guido has accepted the proposal and work has now begun to add support for the new operator: <a href="http://bugs.python.org/issue21176" rel="nofollow">http://bugs.python.org/issue21176</a>
After a few years in Scala, where all operators are methods and vice versa (2 + 3 is just sugar for 2.+(3)), the method-operator distinction just seems <i>weird</i>.
Since this is just a special case of a multiply-and-add indexing loop, maybe they should just introduce some form of tensor notation, so that
A[i,j]*B[j,k] is the matrix product of A and B? That would extend to so many more use cases than just a 2d matrix product.
The PEP claims that:<p>> Matrix multiplication is more of a special case. It's only defined on 2d arrays (also known as "matrices")<p>but this is not true. Matrix multiplication is just a special case of contraction of indices in a tensor (<a href="https://en.wikipedia.org/wiki/Tensor_contraction)—probably" rel="nofollow">https://en.wikipedia.org/wiki/Tensor_contraction)—probably</a> the most frequently used case, but not the only one. I'm certainly not arguing for the inclusion of general tensor-manipulating operators in Python, but it does seem to suggest a sensible alternative to:<p>> For inputs with more than 2 dimensions, we treat the last two dimensions as being the dimensions of the matrices to multiply, and 'broadcast' across the other dimensions.<p>namely, just contract on the inner indices. That is, arr(n1, ..., nk, m) @ arr(m, p1, ... pl) = arr(n1, ..., nk, p1, ..., pl).<p>EDIT: scythe (<a href="https://news.ycombinator.com/item?id=7554013" rel="nofollow">https://news.ycombinator.com/item?id=7554013</a>) already pointed this out in passing.
My issue is not with the matrix-multiplication operator—I'm a mathematician before I'm a programmer, and so am all for it—but with the vector-to-matrix promotions: why not just consistently promote vectors to <i>columns</i> (or rows, if BDFL swings that way)? This would achieve almost the same effect as promoting to rows or columns as needed, and would avoid the non-associativity problem that the PEP mentions.<p>This PEP seems to imply that the cost would be a profusion of superfluous `newaxis`s, but I can't see that: it seems to me that you would need only to remember which kind of promotion works by default, and sprinkle in a `.T` whenever you need the other kind. (Anyone who's uncomfortable with lots of `.T`s in matrix-crunching code is not, I submit, someone who writes or reads lots of matrix-crunching code.)
There are a few handy things that I'd like to see added to Python's syntax. A dedicated operator for matrix multiplication isn't one of them.
I really like this snippet from the justification for the symbol chosen: "APL apparently used +.×, which by combining a multi-character token, confusing attribute-access-like . syntax, and a unicode character, ranks somewhere below U+2603 SNOWMAN on our candidate list".<p>One of the reasons I have been such a fan of Python for so long is the relatively no-nonsense approach to design decisions that many others would have rushed through.
Python's syntax is already pretty ponderous, this kind of thing pushes it rapidly toward bash-like incomprehensibility. I've been a big fan of the language for years but this kind of thing makes me consider jumping to Lua or something which is more sparing with new complicated sigils.
Matlab's approach to using * as the matrix multiplier makes sense, because every numerical variable is an array with integers/floats simply being a 1x1 array. Using .* then as the elementwise version works.<p>I'd have personally preferred to see Python do type testing on the variables - it already does. For example:<p>'quick' + 'fox' = 'quickfox'
3 + 5 = 8
[3] + [5] = [3,5]<p>So why not make it a case where * on an int or float does the 'standard' multiplication that already exists whereas * on an array does matrix multiplication?<p>You arrive at the problem of then not having an element-wise version of the multiplication but it's not as if this solves that problem anyway.<p>What am I missing to make that a problem?
I think "Matrix Multiplication" is a little too specific for a syntax change, but I welcome the addition of a new operator to be overloaded.<p>Am I missing some useful applications of matrix multiplication on a general purpose language?
They gave a rationale for @ compared to other not yet used ascii characters.<p>But they didn't consider a combination of multiple characters, like e.g. 3 * s?<p>(NOTE: Hacker news does not allow typing 3 * in a row)
Personally, I'd really like to see an equivalent in Python to Haskell's `binop` , to turn an arbitrary two-argument function into a binary operator.
Why not use the existing convention for names of infix operators like __mmul__ but allow then to be infix as well.. So, we could write A __mmul__ B.<p>I think this is more clear than @ and is already familiar to programmers that deal with operator overloading methods. It would also enable the addition of arbitrary infix operators to python.
You've got to wonder, does matrix multiplication happen so often and is it so inconvenient to call as a function that it's worth complicating the syntax? I'm really not sure about this one.
Currently, we can use * to multiply two numpy matrix. We'll have two choices, * and @, to do the matrix multiply things in numpy. Is it pythonic? Or should we deprecate * ?
from the pep as to why not using a type that defines _mul_ as matrix multiplication :
"
The result is a strong consensus among both numpy developers and developers of downstream packages that numpy.matrix should essentially never be used, because of the problems caused by having conflicting duck types for arrays
"<p>looks to me like an issue with python lack of static type checking. if you need to define an operator every time two types conflict, you're in for a long list...