Comment by Veedrac

4 months ago

> Let’s start with an example: (2#x)#1,x#0 is code from the official q phrasebook for constructing an x-by-x identity matrix.

Is this... just to be clever? Why not

    (!x)=/:!x

aka. the identity matrix is defined as having ones on the diagonal? Bonus points AI will understand the code better.

while both versions are O(N^2), your version is slower because comparison operation, which affects execution speed. This is suboptimal.

  q)x:1000
  q)\t:1000 sum (til x)=/:(til x)
  889
  q)\t:1000 sum (til x)=/:(til x)
  871
  q)\t:1000 sum (2#x)#1,x#0
  602
  q)\t:1000 sum (2#x)#1,x#0
  599

upd: in ngn/k, situation is opposite ;-o

Unless the interpreter is capable of pattern-recognizing that whole pattern, that will be less efficient, e.g. having to work with 16-bit integers for x in the range 128..32767, whereas the direct version can construct the array directly (i.e. one byte or bit per element depending on whether kdb has bit booleans). Can't provide timings for kdb for licensing reasons, but here's Dyalog APL and CBQN doing the same thing, showing the fast version at 3.7x and 10.5x faster respectively: https://dzaima.github.io/paste/#0U1bmUlaOVncM8FGP5VIAg0e9cxV...

The vibe I get from q/kdb in general is that its concision has passed the point of increasing clarity through brevity and is now about some kind of weird hazing or machismo thing. I've never seen even numpy's verbosity be an actual impediment to understanding an algorithm, so we're left speculation about social and psychological explanations for why someone would write (2#x)#1,x#0 and think it beautiful.

Some brief notations make sense. Consider, say, einsum: "ij->ji" elegantly expresses a whole operation in a way that exposes the underlying symmetry of the domain. I don't think q's line noise style (or APL for that matter) is similarly exposing any deeper structure.