APL and K are still pretty daunting, but I've recently been dabbling in Lil[1], which is something like a cross between K and Lua. I can fall back on regular procedural code when I need to, but I appreciate being able to do things like:
127 * sin (range sample_rate)*2*pi*freq_hz/sample_rate
This produces one second audio-clip of a "freq_hz" sine-wave, at the given sample-rate. The "range sample_rate" produces a list of integers from 0 to sample_rate, and all the other multiplications and divisions vectorise to apply to every item in the list. Even the "sin" operator transparently works on a list.
It also took me a little while to get used to the operator precedence (always right-to-left, no matter what), but it does indeed make expressions (and the compiler) simpler. The other thing that impresses me is being able to say:
maximum:if x > y x else y end
...without grouping symbols around the condition or the statements. Well, I guess "end" is kind of a grouping symbol, but the language feels very clean and concise and fluent.
for that matter, i always wonder how people mistake python for numpy :) they have surprisingly little in common.
but enough talking about languages that suck. let's talk about python!
i'm not some braniac on a nerd patrol, i'm a simple guy and i write simple programs, so i need simple things. let's say i want an identity matrix of order x*x.
nothing simpler. i just chose one of 6 versions of python found on my system, create a venv, activate it, pip install numpy (and a terabyte of its dependencies), and that's it - i got my matrix straight away. i absolutely love it:
assuming you're referring to numpy as to have anything to do with python spec, i totally agree with you. only it doesn't. so don't pytorch and pandas (and good so, poor python doesn't need any extra help to be completely f).
> you get an nxn identity matrix by...
no, man, that's how you get it. really advanced technique, kudos!
i get it by:
id:{...} /there are many ways to implement identity in k, and it's fun!
id 3
+1.00 +0.00 +0.00
+0.00 +1.00 +0.00
+0.00 +0.00 +1.00
but if you can keep a secret, more recently we've gotten so lazy and disingenuous in k land, and because we need them bloody matrices so often now, we just do it like so:
(but of course before we do that we first install python4, numpy, pytorch, pandas and polars - not because we need them, just to feel like seasoned professionals who know what they're doing)
this is of course obvious first idea, but the recipe from above is actually from the official k4 cookbook. t=t is less innocent than it seems, i'm afraid.
Pretty much, yeah! The difference is that in Python the function that calculates a single value looks like:
foo(x)
...while the function that calculates a batch of values looks like:
[foo(x) for x in somelist]
Meanwhile in Lil (and I'd guess APL and K), the one function works in both situations.
You can get some nice speed-ups in Python by pushing iteration into a list comprehension, because it's more specialised in the byte-code than a for loop. It's a lot easier in Lil, since it often Just Works.
A few more examples in K and Lil where pervasive implicit iteration is useful, and why their conforming behavior is not equivalent to a simple .map() or a flat comprehension: http://beyondloom.com/blog/conforming.html
It also took me a little while to get used to the operator precedence (always right-to-left, no matter what), but it does indeed make expressions (and the compiler) simpler. The other thing that impresses me is being able to say:
...without grouping symbols around the condition or the statements. Well, I guess "end" is kind of a grouping symbol, but the language feels very clean and concise and fluent.[1]: https://beyondloom.com/decker/lil.html