7
$\begingroup$

Introduction

In MATLAB, Octave and Julia, matrices are defined extremely easily. The following line defines a 2x2 matrix in any of those languages:

A = [1 3; 4 -1]

Case 1: Python

Someone who's "native" language is Python, told me that the simplest way to accomplish the above goal would be:

from numpy import matrix 
A = matrix('1 3;4 -1')

I see that the official NumPy documentation recommends to use an even more verbose syntax:

"It is no longer recommended to use this class, even for linear algebra. Instead use regular arrays. The class may be removed in the future."

The simplest way to define the matrix is then even more verbose:

from numpy import array
A = array([[1,3],[1,9,-2,1]])

What are the advantages of requiring us to type "array" or "matrix", or the disadvantages that we sacrifice in other languages by not requiring any such words?

I understand that a lot of Python programs don't need matrices, but Python is used enormously in machine learning (it's the most popular language tag in the Artificial Intelligence Stack Exchange), and Quantum Computing (the Python program Qiskit is the most popular tag in the Quantum Computing Stack Exchange), and other areas with enormous usage of matrices, so I wonder what harm/disadvantages the type of functionality described in the first paragraph, would introduce?

Case 2: R

What surprises me even more, is the syntax in R. Unlike Python, which you might say is not designed specifically for numerical computation but is rather meant to be more of a "general purpose" language, R was designed specifically for numerical computing. There are several ways to define a matrix in R and they all seem to have syntax that's as cumbersome as the Python syntax. R has the matrix() function akin to the NumPy function that the official NumPy documentation recommends not to use, and it has other methods that also rely on typing out a function name in words, rather than just having a syntax that's reserved for defining matrices.

$\endgroup$
5
  • 2
    $\begingroup$ Interestingly, APL, where matrices (and higher-dimensional arrays) are bread-and-butter, doesn't have a notation for them either (yet — I'm working on that), but does have a less noisy equivalent of the NumPy syntax: 1 3⍴1 9 ¯2 1. However, this has lead APLers to develop several techniques to get literal matrices into their programs. None of their are particularly pleasant. $\endgroup$
    – Adám
    Commented May 30, 2023 at 6:59
  • $\begingroup$ I think you should distinguish between literal notation, as in [[1,9],[-2,1]] and a more declarative/computational notation like [[2,2],[1,9,-2,1]. Both have their merits, and a language can support either or both. $\endgroup$
    – Adám
    Commented May 30, 2023 at 7:01
  • $\begingroup$ There is a more general question waiting to get out here "what is a good syntax for tensor initialisation?" $\endgroup$ Commented May 30, 2023 at 11:25
  • $\begingroup$ In fact I've decided to ask it - languagedesign.stackexchange.com/q/1290/285 $\endgroup$ Commented May 30, 2023 at 11:38
  • $\begingroup$ Aside: could there be any execution efficiency gained if the "matrix" keyword implied that the object is guaranteed to be rectangular, so the compiler or interpreter knows that all rows have the same length? $\endgroup$ Commented May 30, 2023 at 12:57

1 Answer 1

9
$\begingroup$

I understand that a lot of Python programs don't need matrices, but [...] I wonder what harm/disadvantages the type of functionality described in the first paragraph, would introduce?

Well, you've thrown away the list literal syntax used in nearly every program in favour of matrix literals used by very few, which is a bit of a drawback. The features you are using are from an external library, in any case, so their capacity to make fundamental extensions to the language is fairly limited. There is no reason they (or you) couldn't provide a shorter function for building such a matrix if you wanted, though:

class MatrixCreator:
    def __getitem__(self, *args):
        return numpy.array(args)
m = MatrixCreator()
A = m[[1,3],[4,-1]]

Pretty close? I know you don't like commas, though.

R was designed specifically for numerical computing. There's several ways to define a matrix in R and they all seem to have syntax that's as cumbersome as the Python syntax.

I don't think I'd agree with that characterisation of R, and instead I'd say it was designed specifically for statistical work, which isn't so distant from numerical computing, but R's intention definitely isn't coextensive with MATLAB's. I can understand if matrices are also deemed not-quite-core, or were at the early stages of development. Frankly, though, nobody is arguing that R is a well-designed language and PL people will likely overwhelmingly say the reverse — but it's also very popular and effective with its user base, so what do we know?

R is an interesting case here because it doesn't have literal syntax for nearly anything: even regular unidimensional vectors are written as c function calls. This is a choice, and it's somewhat pervasive in the language that you can alias or replace core function elements.

I suspect that matrix literals, as opposed to data-driven matrix construction, are relatively uncommon across the space of both R and Python programs — though perhaps not in the ones you encounter in your work! — and so it's not really something that would ever be in consideration.


In both of these cases, and in similar questions more broadly, the operative factor is always what you're trading off against including feature X, not what you're missing out on by not having it: could you use that syntax better for something else? is this the kind of program you're trying to enable? what are the maintenance costs of steering into this direction? All of these questions can have different reasonable results, with none of them innately superior.

Once you make some choices, others are determined for you: if the [] characters have been used up already by something high-priority, then the other core way to express constructing a value comes in instead - a function call, and that has a name. Almost everything in almost every language is not syntactically supported, but rests on a generic (usually named) construction like a function or method call, class construction, and so on. That's in a lot of ways why those features exist, so that new non-core functionality can be added in after the fact.

It's unlikely to make sense for Python to provide syntax-level bindings to an optional third-party library occupying core keyboard characters, but R potentially could have, losing out instead on some of the functional behaviour they wanted. Other languages make different trade-offs, and probably most of them make the right ones for them.

Julia has made different choices, and it's entirely reasonable to decide to use it because of those. It's had the benefit of seeing decades of each of the others in practice to work from, and to choose to focus its energies in a particular direction and on a particular set of ergonomic pathways. It may just be more suitable for what you want to do. It doesn't have the same broad-ranging ecosystem outside that domain that Python does, but that may not matter to you—or it may be vital in ruling it out.


There's also a second undercurrent in the question, which is "why aren't all languages like the one I like? I'd like them to be". This is a common feeling; lots of times while writing in one language I wish for a feature I'm accustomed to in another. This isn't one with a tidy answer, but fundamentally this is why there are different languages at all, and those tradeoffs compound with each other to point at radically different results. The Haskell programmers and the Java programmers may wish for lazy evaluation and mutable state in each other's language, even when they're working in their shared domains, but they get different benefits instead.

Why do people use languages that seem suboptimal for their purpose? Sometimes it's inertia, sometimes there are secondary trade-offs that make it worthwhile, sometimes there are ecosystem benefits from libraries or from ease of collaborating with people in different domains. Sometimes one maps better to how they think than another: perhaps we'll get another question asking why MATLAB doesn't use words to describe what you're creating, and instead uses some cryptic punctuation and semantic whitespace. Ultimately, these are often not constructive questions to explore outside of a concrete local situation where standardising on a platform is useful.

$\endgroup$
1
  • $\begingroup$ "It's unlikely to make sense for Python to provide syntax-level bindings to an optional third-party library occupying core keyboard characters" << Well, actually, it was proposed to add operator @ to python, specifically for use with numpy. Operator @ is now officially part of the core language, and any class can implement this operator by including a __matmul__ method, even though no core type implements it, and it is used almost-exclusively by numpy. $\endgroup$
    – Stef
    Commented Jan 31 at 18:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .