Remote-Url: https://beyondloom.com/blog/denial.html Retrieved-at: 2021-09-11 18:00:31.485246+00:00 It is a lazy Tuesday afternoon. Perhaps you were idly browsing your favorite news aggregator, or visiting The Orange Website to wade through murky startup groupthink in search of interesting links.Today, though, you arrived at an enigma. A proprietary, closed-source, commercial programming language. A bizarre anachronism. The programs, if you can call them that, resemble the results of a prolonged fistfight with a keyboard. The language is simply called “K”. You snort at the vulgar presumptuousness of a single-letter name, before self-consciously averting your eyes from the C compiler output in a nearby terminal.One K example looks like this:+/!100Completely illegible. Fortunately, another soul has provided a translation into something intuitive and natural:int sum = 0; for (int i = 0; i < 100; i++) { sum += i; }There is no visible correspondence between the structure of these programs. You discern no parts of speech in the K, no names to grasp onto to extract meaning. Frustrating, and yet… intriguing. K seems to be one of these “code golf” languages designed for writing cryptic one-liners that minimize (key)strokes and demonstrate one’s cleverness. Who doesn’t like to demonstrate their own cleverness? Then you scowl and remember thatclevercode is impossible to maintain.Before a treatise can work its way out of your fingers on the value ofsimplecode which is comprehensible to even the most junior Stanford-educated Google employee, (optimization being the root of all evil, as you once read, paraphrased) someone else points out that a more direct translation intoanotherlanguage might look like:sum = range(100).reduce(plus, 0)The correspondence is clearer now. If each punctuation character in the K is a separate part of speech, and you reverse their order…+ / ! 100 plus reduce range 100Backwards! You stifle a chuckle. What next? Still dubious, but increasingly invested in this puzzle, you spend some time reading more about K. A fewroguelunaticshavefurnishedmostly-working open source interpreters for dialects of the language, so you give them a try. You read a fewessaysandtutorials, flip through themanual for K2that serves as the primary comprehensive reference for the language, and have a go at solving someProject Eulerproblems.In the course of your reading you briefly encounterJandAPL, which seem evenmorealien than K, and yet… the same in many ways. J and APL have K’s right-to-left evaluation (in annoying defiance ofPEMDAS, for some reason), the/symbol means “reduce”, and you can add 5 to an entire matrix at once as easily as a single number.Whyyou would want this property remains elusive- it seems ratheracademicandmathy- but you can’t help but admit that it’s rather neat. You have a growing impression that K is not simply a one-off oddity, but rather a member of a whole family tree.Fine, K has some appeal. Being able to dash off,/to flatten a list is nice. The “grade” operatorsseemed like a clumsy way to sort at first, but you’re starting to see that “permutation vectors” have many other uses. There’s something deeplyrightabout how list indexing and function application are the same operation. K seems too domain-specific to use forrealwork, but maybe it would be handy to implement some of the K primitives as a library for your favorite language?The symbols still feel like a problem. Wouldn’t it be clearer and more readable to simply use spelled-out names? Maybe instead of writing:*>#:'=You could factor the definition apart and use more explicit syntax:groupIndices: {[list] : =list } countEach: {[dict] : #:'dict } maxIndex: {[list] : *>list } mostCommon: {[list] : maxIndex[countEach[groupIndices[list]]] }In principle, this should be more readable and easier to understand. You have dutifully broken down the definition into reusable parts and given them clear, meaningful names, a best-practice that you learned in your earliest programming courses and have carried forward throughout your professional career. Still,this timethere’s something worryingly unsatisfying about the results. The name “mostCommon” is longer than theentire definitionin K if you write it more succinctly.It is possible to write K as if it were a strange-looking Lisp,M-Expressionsand all:fibs: {[n] if[less[n;3];:iota[n]] fibrec:{[list] if[equal[n;count[list]];:list] a:list[minus[count[list];1]] b:list[minus[count[list];2]] :_f[join[list;plus[a;b]]] } :fibrec[(0;1)] }Or you could express the same idea without conditionals, recursion, or any explicitly named variables:{x#x{x,+/-2#x}/0 1}Does giving a K idiom a name make itclearer, or does it obscure what isactually happening?sum: +/ raze: ,/ ordinal: < max) { max = list[i]; } }You suggest an alternative, wincing slightly at the lambda notation you need to avoid running afoul of JavaScript’s variadicMath.max():list.reduce((x,y)=>Math.max(x,y))Your suggestion is rebuffed as cryptic and overly complex. Lambdas are hard to understand, not to mentionreduce(). A for loop is much more intuitive, natural, and readable, it is argued. If you used clever tricks everwhere in the codebase, it would be impossible to maintain. A compromise is committed:let max = list[0]; for (let i = 0; i < list.length; i++) { max = Math.max(list[i], max); }On The Orange Website, someone has started a thread about an obscure language with a single-letter name. Commenters are quick to express incredulity at how unreadable it is.Leaning back in your chair, you think to yourself:|/back