K programming language (2005)
archive.vector.org.uk
archive.vector.org.uk
However, beyond the basics, a lot has changed since (current commercial version is K4, current dev is K6 AFAIK): Dictionaries have become better integrated in the language, the database layer was rolled into the language, the integrated (bare bones and milspec-looking but ultra effective) electric GUI was dropped, http and web (as both client and server) were added to the core, 64-bit integers, nanosecond timestamps, GUIDs were added as core types, and probably a few more things I forgot.
If you find this article interesting, you may want to experiment with JohnEarnest's ok [0], which provides graphical playground (implemented in JS and runs everywhere) and also read Q for mortals[1] - Q is a syntactic-sugar version of K4, though still the same language underneath.
The K2 GUI was very handy for programmers, for rapid prototyping, but it is impractical to use it for making visually polished UIs you would give to a customer.
If a feature of K doesn't pull its weight, it is removed.
Alternatively, there's the free and open source Kona, which is an implementation of K3, the preceding version.
For playing around with the basic constructs, https://github.com/JohnEarnest/ok is nice (and itself pleasingly concise). Currently targeting the K6 dialect, I think. It doesn't really have any of the "database" side of things, though.
It helps a lot more than a lot: Small is everything.
"Main memory" is something like 1000x slower than "L1 CPU cache", so if your whole program lives in L1 you only pay to receive data, which streams in as fast as main memory can. How can you possibly go any faster than that?
The interpreter looks a lot like this[1], scan a character, do something with it. There's no scanning phase, or AST, or very much analysis at all. Being simple helps keep it small. Writing dense makes it easy to see (without scrolling) similar code which can be refactored into less space. This is how small (dense) source code can also help make small object code. This is how small (dense) source code is fast!
[1]: nsl.com/papers/origins.htm
Once you've done all that, vector instructions and multi-threading can help eke out a little bit more speed. Recognising a couple characters at a time and treating them specially can sometimes help as well, but it also can cost a lot of object size quickly, so there needs to be some balance.
the missing bullshit parts :)
also simplicity and good memory access patterns
> vector instructions
if you write simple loops in c, compilers are good at generating those
> Does the K interpreter pattern-recognize
afaik some, like *| but fewer than dyalog
The design paradigm of k is to memory map the data and then "forget about the filesystem"; transform data in memory, instead of reading and writing "files".
The slowest part of working in k, for me, is the process of reading files into memory. And I run kernel and filesystem entirely in RAM (mfs and tmpfs); no disk is involved.
If there are other software authors who also adopted this paradigm of avoiding I/O, I would like to know of them.
Ideally I would prefer a system with sufficient RAM, without the need for "short-term" disk storage and thus without the need for virtual memory. Because today, I have the RAM I need. I have no requirement for short-term disk storage.
But like the rest of us, I use kernels that date back to a different era. These are kernels that assume insufficient RAM, the presence of a disk and the need for a "swap device" to do work. Disk I/O is a major part of that paradigm and has been embraced by software authors.
To me, disk is slow. Even SSD. I seek a different paradigm, not one still focused on secondary storage. k is the closest thing I have found.
https://en.wikipedia.org/wiki/Shadow_IT
The author of that article has a very biased view tho'. An organisation that finds a lot of shadow IT happening probably ought to replace the head of the IT department since he or she is clearly not delivering what the users actually need.
From the link: Shadow IT can act as a brake on the adoption of new technology
LOL!!!
https://github.com/Morgan-Stanley/hobbes
The PL is a little different (very similar to Haskell), interoperation with C/C++ is much more direct, and it's also suitable for low-latency applications (where the boxing overhead in K would be unsuitable).
K
+/&~&/(!1000)!/:3 5
Q sum where any not {(til x)mod y}[1000] each 3 5If you want a slightly more “English like” language which still gives you the array stuff, Q is built on top of K4 and might fit the bill
This seems like a really weird thing to optimise for - would you mind saying more? I've never found myself thinking "man, I wish my function could _do more_".
> This syntax is very readable.
Objectively, by any measure, this isn't true.
Readability is relative. It's a category error to speak of it without saying who the reader is. Is Sanskrit readable?
Completely disagree, and I think the people spending the 2010's clearing up screeds of idiomatic perl 5 would side with me :)
Point being that translating from unfamiliar syntax to familiar is always a challenge.
Every summer we spend about a week training interns with K, and they proceed to read, modify and write real production code with it during their tenure. Interns come from a mix of backgrounds- computer science, various engineering degrees, etc. This seems compelling evidence that K is learnable.
If you find K unreadable, consider spending a week or two seriously working with it. You might be surprised how you feel afterwards.
Right, but the one follows from the other.
I'm passingly familiar with K, Q, and a+. I've worked with Borror and I kind of own an a+ compiler. I think if you define "readable" to mean "you can learn it with two weeks intensive tuition" the fine, yeah, it's readable. But to me, lightning-fast speed doesn't make up for terse-to-the-point-of-dumb syntax.
+/&~&/(!1000)!/:3 5
Reads like a cruel joke to me. It's unreadable and it breaks everything we know about writing good software, and to pretend otherwise kinda comes across as macho BS. Sorry. I don't know why developers in Whitney's programming languages all have this kind of snow-blindness to the clear failings of the language. I don't know why number of characters of code is the thing we're optimising for in 2018. It's not like you're firing bytes over a 56k modem.No, but I also don't find myself wishing the entire project read like regex does. "If only our entire suite of enterprise software was made up of regexes..."
Some time ago I built an environment for livecoding graphics experiments with K, and the concision of the syntax makes it delightfully easy to experiment and make changes as I build up programs piece by piece. Here's a recording I made which illustrates all the intermediate steps of a simple way to draw a Voronoi diagram:
https://i.imgur.com/YZkYyDs.gif
K notation is a powerful medium of communication when I'm whiteboarding ideas with coworkers, scribbling on a napkin, or tapping an idea into my phone on the subway. I don't write K because I think doing so paints me as some sort of Ubermensch, I write K because I find it crisp and beautiful; An elegant K solution to a thorny problem is poetically satisfying!
I use k/q on and off and after a couple of weeks away, you basically need to relearn it. The massive advantage of R and Python is even after time away, it’s still perfectly legible.
Breaking stuff down costs, as well - you have to make it clear how something is going to be used. You might write a helper function for one bit in particular, and then rely on additional levels of abstraction to make it clear how this function should be used.
Instead, if you can allow your functions to become semantically larger, you don't need to explain and protect your modularisation. Helper functions with one use are inlined (it's very common that these things have names longer than their definition). Instead of a large tower of abstraction, you just have two levels: the level of the data, and the level of the problem. Your entire program is written as functions, each of which does something in the problem domain, and for each, each definition is immediately clear about what it is doing with the data.
There was an article here, a while ago, called 'smaller code, better code', and with accompanying comments, that explain this better than I can.
Although I stopped using Windows, X11 and Mac a long time ago, I have tried k2 on Windows and it is extremley fast, irrespective of whether the computer is old and "underpowered". I used it to instantaneously generate plots and charts from the command line, instead of driving Excel with some scripting language. This is software from the late 1990s early 2000s.
RosettaCode wiki needs to fix its k entries or turn off the silly Cloudflare email protection or whatever is causing the problem. The "@" symbol and subsequent characters are being replaced by "[email protected]".
https://rosettcode.org/wiki/Category:K
k4 can be integrated into daily use in UNIX-like OS for text processing.
Professional example: https://github.com/adavies42/qist/blob/master/lib/awq.k
Amateur example: (remove all duplicate lines)
AWK
#!/bin/sh
awk '!a[$0]++' < $1 > $1.tmp;
exec mv -v $1.tmp $1;
k4
#!/bin/sh
exec echo "k).Q.fs[l:0::\`:$1];l:?:l;\`:$1 0:l"|exec q >&2;
Experiment: keep increasing the size of the file passed as $1 until the AWK version fails.Padding Can Truncate (Done)
In k5, padding was treated as a minimum size for the output string:
2$"abcde"
"ab"
6$"abcde"
"abcde "
In k6, as in older Ks, padding will produce a string with an exact length, truncating if necessary: 2$"abcde"
"ab"
6$"abcde"
"abcde "
Is this correct? / k4
6$"abcde"
"abcde "
2$"abcde"
"ab"
/ k2
6$"abcde"
" abcde"
2$"abcde"
"de"