10 ms·
ngn/k, an AGPL K interpreter
- OskarS 7y agoIs K [0] in some sort of competition with J [1] about who can write worst, most unreadable and unmaintainable C code possible? [0]: https://bitbucket.org/ngn/k/src/master/m.c https://bitbucket.org/ngn/k/src/master/m.c [1]: https://github.com/jsoftware/jsource/blob/master/jsrc/v2.c https://github.com/jsoftware/jsource/blob/master/jsrc/v2.c
- atemerev 7y agoThere are people who value brevity and minimal amount of code above everything else. Arthur Whitney, the author of K, doesn't even use scrolling — everything he reads or writes has to fit on a single page.
- tgv 7y agoBrevity should not be an excuse for obscurity and illegibility. I get it that you assign a short name to central data structures, but all those two character identifiers...
- tluyben2 7y agoAs this thread and post proves, quite a lot of people have no issue reading + understanding it. One of the goals to fit a lot of functionality on 1 screen which helps, especially when you get older, but it always helped. No scrolling, searching, trying to find in which abstraction in which of the 1000s of files with 'readable' code things are stored. You open 1 file and yes it will take you (a lot) more time to read the same length (in lines) page of, let's say Java or C#, but in those languages you will need often 10s, 100s or even 1000s of these pages (in many different files because that's 'readable') to write the same functionality idiomatically in that language as that one pager in this style. So people who take the patience to read and understand this will actually be more productive in my experience: I am claiming that it will take most people (a lot) more time to read and understand this code if it was written in a traditional way in C or whatever, with proper variable names, spread over many nicely created .h and .c files than it takes someone who has done this before to understand and work on this. And that gets more obvious when you actually start using APL/K/J which allow even more expressiveness into the language and will let you even compress more functionality in less characters. However it does not naturally scale to teams. But each way of working has its own strengths and weaknesses; if you are aiming for large teams working together on large projects, I would not recommend this. That is not because of readability, but because the code is so terse that you would, even with 2 people, be changing the same code a lot of the time, so it's more efficient to do it alone or in pair programming (which does work well; also remotely in an APL-like in my experience).
- msla 7y ago> As this thread and post proves, quite a lot of people have no issue reading + understanding it. This thread, like this implementation, is a troll, a joke, and everyone trying to appreciate this thing as a language is being pranked.
- kick 7y agoThink of it like it's math. If you have to explain the value of e every time you use it, the value of your work to onlookers diminishes, and it can no longer be held in the mind of any reader.
- kick 7y agoSnide remarks are dull, and HN's guidelines explicitly recommend against cheap humor. Every time K is posted to HN someone makes this exact style of comment in an attempt to be funny, but it's entirely unoriginal. There's good reason as to why C written by APL programmers looks as it does, and shallowly dismissing it does a disservice to everyone.
- msla 7y agoI still wonder if this is the form the author of the code uses to write the program.
- warpech 7y agoIf you find it unbelievable that code like this is written by hand, read this short explanation about “a very unusual style of C” [1]. Fastai has a guide how to write Whitney-style code in Python [2]. Thre is a relevant thread in HN [3]. [1] https://github.com/kevinlawler/kona/wiki/Coding-Guidelines#this-is-a-very-unusual-style-of-c https://github.com/kevinlawler/kona/wiki/Coding-Guidelines#t... [2] https://docs.fast.ai/dev/style.html https://docs.fast.ai/dev/style.html [3] https://news.ycombinator.com/item?id=19481505 https://news.ycombinator.com/item?id=19481505
- saagarjha 7y agoThis isn't even unusual "I want to write K in C" style, it's specifically being annoying: https://bitbucket.org/ngn/k/src/master/m.c https://bitbucket.org/ngn/k/src/master/m.c. I mean, for goodness' sake, it's pivoting the stack in x86_64 assembly to implement _start!
- ngnk 7y agoany ideas for a more compact and efficient way to get argc and argv on both linux and freebsd without bringing in libc?
- saagarjha 7y agoPortably? No.
- duskwuff 7y agoGiven that the interpreter makes system calls directly using inline assembly [1], I suspect that any hope of portability went out the window long ago. [1]: https://bitbucket.org/ngn/k/src/b54eb5cfea5eb821fe1de68d2a8ad4b97f88e765/k.h#lines-63 https://bitbucket.org/ngn/k/src/b54eb5cfea5eb821fe1de68d2a8a...
- ngnk 7y agoacross architectures: you're right, as of now it's x86_64 only across operating systems: it works on linux and freebsd as-is (thanks bakul), and with a few changes on windows+libc (thanks ktye) - https://github.com/ktye/i/tree/master/_/ngn https://github.com/ktye/i/tree/master/_/ngn though i personally never use windows
- saagarjha 7y agoThe code is unreadable, formatted in the style of an IOCCC entry–and this looks intentional. I wonder why.
- smabie 7y agoIt’s just a different style. After using kdb+/q for aoc2019, I quite like the no space one-line style. I find the code easier to read and remember. I think most people who have tried an APL derived language also agree. It’s important that many/most cultural norms are not optimal, they are arbitrary. So don’t immediately discount something for looking weird.
- saagarjha 7y agoI refuse to believe that the call to main here is a matter of style: https://bitbucket.org/ngn/k/src/master/m.c https://bitbucket.org/ngn/k/src/master/m.c.
- lifthrasiir 7y agoI was actually very amused when I found that even VimScript is written in this style (look at the first line): https://bitbucket.org/ngn/k/src/master/vim-k/syntax/k.vim https://bitbucket.org/ngn/k/src/master/vim-k/syntax/k.vim
- smabie 7y agoWhile I wouldn’t write C like that, that’s how Arthur Whitney and others write code. The entire kdb+/q codebase is structured like that. And considering the success and insane performance of the system, I believe there is something to it. The point of this style isn’t obfuscation, it’s clarity and compactness. The compactness boosts the signal to noise ratio and allows the programmer to retain more information in working memory. I haven’t programmed C like that and wouldn’t, but I definately understand and respect the theory behind it. I have on the other hand written q like that, at first skeptical of the style. But after a couple days, I wouldn’t have it any other way. Being able to fit your entire program on a single screen has pretty profound productivity benefits. It also makes IDEs unnecessary. For other code structured like this, check out Kona, J or kdb+/q. In general, I don’t think refusing to believe is a very useful attitude. See: Chesterton’s Fence.
- emmanueloga_ 7y agoAuthor has a page [1] listing a few diff implementations of "K" [2]: * A proprietary array processing language * A variant of APL with elements of Scheme * K serves as the foundation for kdb+, an in-memory, column-based database * Advocates of the language emphasize its speed, facility in handling arrays, and expressive syntax. 1: https://ngn.bitbucket.io/k.html https://ngn.bitbucket.io/k.html 2: https://en.wikipedia.org/wiki/K_(programming_language) https://en.wikipedia.org/wiki/K_(programming_language) Edit: some examples of idiomatic code (I assume...) * https://github.com/KxSystems/cookbook https://github.com/KxSystems/cookbook * https://code.kx.com/phrases/ https://code.kx.com/phrases/ * https://github.com/KxSystems/javakdb https://github.com/KxSystems/javakdb
- kick 7y agoMore fun examples of k: nsl.com kparc.com
- 3xblah 7y ago"64-bit spyware" Telemetry?
- ngnk 7y agoi changed it to "telemetry". i'm not really sure what to call it. they are upfront about it in the clickwrap eula but the data is not anonymized (see section 1.5a - in k ".z.u" means username) and you are not allowed to obstruct connectivity. it's not quite spyware either, as it happens with your consent.
- userbinator 7y agoit's not quite spyware either, as it happens with your consent. All the famous spyware I'm aware of which you had to have initiated the action to install includes an EULA which does mention the data collection. That doesn't make it any less spyware.
- RodgerTheGreat 7y agoOne subtle feature of oK is that it supports the creation of mutable closures. "f.d", where "f" is a function and "d" is some dictionary, will attach the dictionary to the function as if it were the global scope. You can then later use ".f" to extract that dictionary from a function to inspect it. This mechanism allows you to violate referential transparency (which is why Arthur doesn't like it), but you get a powerful mechanism for sandboxing code which can also permit writing code in an "OOP" style, if desired. Here's the feature in action: f:{a+::x}.[a:10] {[x]a::.`a+x} f 30 40 f 30 70 f 30 100 .f [a:100] Naturally, if you have not explicitly re-bound the closure of a function, .f gives you access to that function's natural scope: a:99 99 b:"text" "text" .{} [prm:{[x]{[x]$[x;,/x ,''o'x ^/:x;,x]}@$[-8>@x;!x;x]};in:{[x;y]~^y?x};a:99;b:"text"] Nifty, eh? oK also supports unlimited lexical closure, which is a bit unusual among K interpreters; usually they either eschew closure entirely for simplicity or (as in k3) allow functions to close over a single scope.
- chrispsn 7y agongn wrote: i'm not trying to purposefully copy [Arthur's] style. i've always been trying to write shorter code - there are public traces of how that evolved in ngn/apl and in dyalog's ride. i acknowledge that after seeing some of arthur's code, including b, my mental threshold of what is considered acceptable dropped significantly. once you accept certain principles about the code, for instance that it's more important to be able to hold it at once in your head than to be able to explain it to the uninitiated, this style becomes more efficient and more pleasant ... if you seek simplicity, this style is to a large extent discovered (as opposed to invented) complicated things can be arranged in many ways. simple in few. that's why it always looks like entropy is increasing in the physical world :) https://chat.stackexchange.com/transcript/message/52953241#52953241 https://chat.stackexchange.com/transcript/message/52953241#5...
- RodgerTheGreat 7y agoA fun and somewhat illuminating exercise in C is to simply try minimizing the number of semicolons in your programs. Pick any comfortable, well-defined task and spend a few hours refining an implementation. Fewer semicolons means fewer statements. Apart from simplifying the structure of ones code overall, this also drives writing in a somewhat more functional style. You will find yourself taking advantage of the comma and ternary operators more, if you don't already. Macros are another tool for decreasing repetition. So is expressing programs in a "data-oriented" style, using lookup tables instead of explicit conditionals. If something is used only once, inlining it can reduce the number of distinct statements.
- kick 7y ago'tlack: It only took ten years for a non-toy one to come about! (Less if you count the one that got sued off the internet from the Morgan Stanley employee.) https://news.ycombinator.com/item?id=944961 https://news.ycombinator.com/item?id=944961
- saagarjha 7y agoSomehow, I don't think they would appreciate this as much as you might have hoped: https://news.ycombinator.com/item?id=945093 https://news.ycombinator.com/item?id=945093
- kick 7y agoIt was more a joke on "Ten years!" rather than assuming anything. I've already read that comment.
- tlack 7y agoFor the record, I'm more open to this style now so I'd like permission to take a few steps back from that statement in 2009 (and probably most of my others that year!). Coding in a terse style really does have some benefits. You can understand more program flow at one time and you can easily see larger patterns. Another recent discussion https://news.ycombinator.com/item?id=21890259 https://news.ycombinator.com/item?id=21890259
- kick 7y agoI'm really happy you've changed your mind on this! Thanks for being open-minded!
- beefhash 7y agoAnd Google probably won't touch it anyway because AGPL.
- 3xblah 7y agoDownload links: https://bitbucket.org/ngn/k/downloads/k https://bitbucket.org/ngn/k/downloads/k (Linux binary 64-bit) https://bitbucket.org/ngn/k/get/master.tar.gz https://bitbucket.org/ngn/k/get/master.tar.gz (Source code) No Javascript required
- ngnk 7y agoi'd encourage people to compile from source. the binary in "downloads" was compiled without the "-march=native" flag, in order to support older cpus, so it's a bit slower. also, i don't intend to update it regularly - i'll probably remove it in a couple of days.
- deleted 7y ago[deleted]
- EdSchouten 7y agoYou could argue that the license of the code, in this case AGPL, is irrelevant. I don’t think the source code is any easier to read than disassembled output.
- beagle3 7y agoYou could say a similar thing about Japanese text if you don’t read Japanese - “copyright isn’t relevant, who would ever want to copy this gibberish?”. As people in this and similar threads mention - it is easier to read; in fact, it is easier to read than even the preprocessed output, if you are familiar with the style and concepts.
- gnulinux 7y agoWhat a disappointing comment. This is like saying MIT/GPL/AGPL in programming languages most people don't understand is irrelevant, since most people wouldn't wanna read/copy/edit code anyway. By that logic, there is no value using open/free license in niche languages. Even though you don't understand this language/style, doesn't mean a user may not want to refer to source code, or someone may want to contribute to the project.
- ngnk 7y agothe agpl is not so much about making concise code pleasant for the masses, as it is about making its freedom viral
- scottlocklin 7y agoYes, you need to understand a bit of APL to grok the style, but I don't know why it bothers people so much. I'm guessing because it involves people actually using the macro system for something interesting. Somehow lisp gets a pass. Personally I think stuff like the DO macro (F/Fj in this code base https://bitbucket.org/ngn/k/src/master/k.h https://bitbucket.org/ngn/k/src/master/k.h) should be used everywhere to the extent it is part of the C standard. If compilers were aware of it, there are significant optimizations which could be made. It's dirt simple and saves considerable typing and eliminates lots of potential for error.
- msla 7y ago> Somehow lisp gets a pass. OK, which is more readable: (setf (car lst) "value") Or: (rplaca lst "value") I think the one which allows me to learn "setf's destination is the first parameter" and forget the rest is easier by far. setf is glorious macrology: It allows people to write arbitrarily complicated datatypes and have assignment just work, reliably. But the problem with this code isn't the macros. It's the fact the author types like they're being charged by the character and taxed for whitespace. The macros are amazing to the extent they allow this sort of thing. Blaming them for it is wrong, but judging by the only standard that matters, readability, this is not a good coding style.
- RodgerTheGreat 7y agoYour example neatly demonstrates that your definition of readability is based on familiarity. What does variable assignment have to do with the Contents of Address Register, anyway? In the absence of familiarity, minimizing the number of moving parts and factoring out repeated patterns still has intrinsic value for aiding understanding.
- msla 7y ago> Your example neatly demonstrates that your definition of readability is based on familiarity. What does variable assignment have to do with the Contents of Address Register, anyway? I explained myself right below my examples. > In the absence of familiarity, minimizing the number of moving parts and factoring out repeated patterns still has intrinsic value for aiding understanding. And now you're repeating what I said.
- posterboy 7y agoThis must be the famous write once read never coding style I've heard so much about, a bit like my FINO list of bookmarks, where project like this one are always welcome
- dang 7y agoThis is precisely explained by the quote elsewhere in the thread: once you accept certain principles about the code, for instance that it's more important to be able to hold it at once in your head than to be able to explain it to the uninitiated, this style becomes more efficient and more pleasant
- 7thaccount 7y agoAny doc on how IO and other things work in this lang? The official K doc is pretty bad, so I can't exactly go there lol.
- ngnk 7y ago0:"path" /read lines "path"0:("line1";"line2") /write lines 1:"path" /read bytes "path"1:"content" /write bytes
- 7thaccount 7y agoThanks ngnk, but what if I can't read the entire file into memory (Ex: 20 GB file)? Are there any streaming words?
- ngnk 7y agoreading is done with mmap. it returns instantly and then loads memory pages from disk only when you use them.
- 7thaccount 7y agoSo it uses memory mapped files for all operations? So whether the file is 1 MB or 1 TB, it'll read what it can via streaming? Sorry, not knowledgeable here. Sounds neat though.
- ngnk 7y ago1:x uses mmap, so it would return instantly no matter how large a file you give it 0:x uses 1:x and then it splits the content into lines. unfortunately splitting requires copying, so you'd be limited by the amount of ram (let's ignore "swap"). i don't use mmap for writing/amendment yet. i'll be working on it. the way modern hardware works is like this: every process run by the os has its own view of the (typically 48-bit) address space. a process can request from the os that a part of that address space be "backed" by a certain file. this means that every time the process touches (i.e. tries to read or write) a virgin memory page there (usually page=4k, always aligned), the os will be automatically notified and will make sure to fill it in with actual content from the file, before the process even knows. from that point on, the page will occupy physical ram. if the os is low on memory later, it may decide to free up the page and return it to its previous state. in effect, data from disk (or any disk-like storage) can be "streamed" while your program uses ordinary array indexing. the word "streaming" though implies reading from start to end in order (which is additionally sped up by prefetch, but that's a different story..); memory mapping is more general - it allows random access.
- chrispsn 7y agoBizarre that this thread contains virtually no discussion of the technical merits of the end product (performance and size) - just the coding style.
- kick 7y agoRight? I found it immensely disappointing.
- svan99 7y agothis is awesome. Congratulations!