Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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.

[1]: https://beyondloom.com/decker/lil.html



I assume this is the same as this?

  # python
  [127 * sin(x * tau * freq / samplerate) for x in range(samplerate)]


For that matter,

  # python
  from numpy import sin, arange, pi
  127 * sin(arange(samplerate) * 2 * pi * freq / samplerate)


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:

  np.tile(np.concatenate([[1],x*[0]]),x)[:x*x].reshape(*2*[x])
and now lets see just how obscure and unreadable exactly the same thing looks in k:

  (2#x)#1,x#0
no wonder innocent people end up with brain aneurisms and nervous breakdowns.


That is wildly disingenuous. Assuming you've imported numpy as np, you get an nxn identity matrix by doing

   np.identity(n)

http://numpy.org/doc/stable/reference/generated/numpy.identi...


> That is wildly disingenuous.

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:

   &3
  +1.00 +1.00 +1.00
  +1.00 +1.00 +1.00
  +1.00 +1.00 +1.00

   =3
  +1.00 +0.00 +0.00
  +0.00 +1.00 +0.00
  +0.00 +0.00 +1.00
(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)


i'm a fan of

    t=\:t:!x


> t=\:t:!x

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.

in k7/k9, we can:

  10^@[100#0.;11*!10;1.]    /just for more lulz
there's also a way to mutate it in place!


nice :) also see here:

https://news.ycombinator.com/item?id=45603661

HN is such a sweetheart. i should check in more often.


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


And in Julia it’s foo.(x).


julia is cool, hands down.

only typical k binary will be less than 200kb and doesn't need stdlib. it still needs a few syscalls, but we're working on that.

and julia has this small and insignificant dependency called llvm. i bullshit you not:

  kelas@prng ~ % cd /opt/llvm-project
  kelas@prng llvm-project % du -hd0
   14G .
  kelas@prng llvm-project %




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: