ketralnis 11 years ago
    f:<:`:index.txt                     / Open message log append-only
    h:("\n"/:0::`:index.txt),"\n"       / Load message history from log
    .z.po:{(-:.z.w)h}                   / On join, send full message history
    .z.ws:{s:(" "/:($"du"$.z.Z))," ",x; / On message, add server timestamp
        {(-:x)y}\:[!:.z.W;s];           / Fan out to other connections
        h::(h,s,"\n");                  / Update message history in memory
        (-:f)s}                         / Append to message log file
    .z.ph:{"\n"/:0::`:chat.htm}         / Serve static client app

That is really quite inscrutable

  • srpeck 11 years ago

    Is q more readable to you?

      file:hopen`:index.txt                       / Open message log append-only
      history:("\n"sv read0`:index.txt),"\n"      / Load message history from log
      .z.po:{neg[.z.w]history}                    / On join, send full message history
      .z.ws:{s:(" "sv(string"du"$.z.Z))," ",x;    / On message, add server timestamp
             {neg[x]y}\:[key .z.W;s];             / Fan out to other connections
             history::(history,s,"\n");           / Update message history in memory
             (neg file)s}                         / Append to message log file
      .z.ph:{"\n"sv read0`:chat.htm}              / Serve static client app
  • RodgerTheGreat 11 years ago

    Have you ever read any documentation, tutorials or explanations of K? It seems rather odd to expect to be able to understand a programming language without learning about it first.

    • jnbiche 11 years ago

      > It seems rather odd to expect to be able to understand a programming language without learning about it first.

      Really? You can't understand a new language that's in the same general paradigm as one you know already? Because I can, and I'm no PL genius. I've been able to very quickly understand code written in Swift, Ceylon, Pyret, Rust, Nimrod, and various other new-to-me languages in the past few years.

      But I can't make heads or tails of K. And that's clearly the way it's meant to be. It's the epitome of an esoteric language.

      • RodgerTheGreat 11 years ago

        That's exactly it- K isn't in the same general paradigm as those languages. K resembles APL and other array programming languages. Syntax among those languages differs in some ways, but the most basic elements are the same. If you knew APL or J, K wouldn't look so alien.

      • beagle3 11 years ago

        That's because Swift, Ceylon, Pyret, Rust, Nimrod make (relatively) small changes in syntax and semantics compared to Python, Java, C and friends - this is the Algol family of languages if you are old enough (and the "C" family if not).

        Can you read Prolog (assuming you're not fluent in it already)? It is a little farther along from Algol - it is generally verbose, but control flow is implicit (by failure, and negation IS failure), except where you make it explicit by saying '!' (read: "cut"), which means "never backtrack through this point". And there's no assignment, but unification plays a similar part - except it is much weirder (to the uninitiated).

        K is of the APL / J mold, which is much farther away from Algol and Prolog. It's mostly functional. It takes orthogonality beyond where Haskell does. Examples that might make you look again:

        "flatten" (convert recursively nested list/tree to one-level list with the same order as a DFS scan) is written ",//"

        "decode run length decoding" is written ",/#/'" (courtesy of https://github.com/JohnEarnest/ok/blob/gh-pages/examples/run...

        Now, these 3-char and 5-char examples are not predefined in any way; They emerge from composing the semantics of the individual characters that make them. Let that sink. Are you aware of any other language in which a straight concatenation of 3 primitives generates a "flatten" function? 5 primitives generates a "run length decoding" function? Something about K/APL/J is distinctly different. And if you believe that it looks different becuase it's "the way it's meant to be", you're missing out on a lot.

        • klibertp 11 years ago

          > any other language in which a straight concatenation of 3 primitives generates a "flatten" function?

          Does J count? ;)

          A quick look here: http://rosettacode.org/wiki/Flatten_a_list seems to suggest that in most languages you need at least ~5 primitives (I'm counting for example pattern matching, 'rec' qualifier in OCaml, named let in Scheme etc. as single language primitives, maybe that's too restricted).

      • klibertp 11 years ago

        > various other new-to-me languages in the past few years

        Here's your answer: new-to-you, yet very similar to whatever you knew before. Try Oz, Mercury, Lisp, Forth, Avail, Red/REBOL, Clean or J to see how little you actually know about programming languages.

        I don't mean this as an insult, it's just that PL design and research is a HUGE field with people devoting all their academic careers to it; it's only natural to expect most of such a field be unfamiliar and inscrutable if you're not working in it.

    • bkeroack 11 years ago
  • Avshalom 11 years ago

    All it's doing is opening a file, connecting to other clients and appending the messages between clients to the file.

    What you're missing is that K automatically sets up an environment with the necessary pieces in place. A server, the sockets, a type of reactive/eventloopy environment.

    Everything else is just function call/index/assignment and some mappy/foldy stuff

    In some ways its the same reason Mathematica seems so magic sometimes.

geocar 11 years ago

Looks really good!

    F:"\n"/:0::;C:,[;"\n"];I:`:index.txt;f:-<I;h:C F I;H::F`:chat.htm
    .z.ws:{s:(" "/:($"du"$.z.Z),,x);{x y}\:[-!.z.W;s];h,::C s;f s}
    .z.po:{(-.z.w)h};.z.ph:{H}

1. "\n"/:0:: occurs twice and can be made a function (F)

2. You can project the `y` argument by itself (C)

3. Shorten symbols (I)

4. No need to (-f) all over the place when -< will do. (f)

5. You can load chat.htm once (H; .z.ph), but unfortunately K4 won't notice changes to the file, so am a bit divided about this one.

6. Save brackets! Join-enlist (,,), negate til (-!), and amend (,::) (.z.ws)

  • srpeck 11 years ago

    Thanks for the feedback; I pushed your cleaned up version to Github (https://github.com/srpeck/kchat/commit/5669fcca67fa609a9128b...).

    As for your comment in #5, I noticed that I can hot load new versions of the server and client without impacting the existing clients' web socket connections. A production change to chat.htm only requires me to \l chat.k; any existing connections still have the older client running without interruption until they refresh, but all new connections get the new client. However, I am not all that concerned about hot loading new versions, as this is only deployed for a small team on the intranet.

    • geocar 11 years ago

      Indeed!

      I sometimes use emacs and use an after-save-hook to send a command (e.g. to reload a file).

doublerebel 11 years ago

Fantastic, I've been really interested to see a nonfinancial application of k that I could compare to implementations in languages I'm familiar with. If anyone else knows of other such k applications please share them!

jnbiche 11 years ago

Forget Perl, this is serious write-only software engineering.

I mean, I'm a language polyglot, and I think these languages are probably great for multidimensional array processing. But for general purpose programming, not so much.

But cool hack.

  • mmagin 11 years ago

    Every time these k folks show up on HN, it feels like Chuck Moore and Color Forth.

  • geocar 11 years ago

    Don't dismiss things you don't understand: I think array programming is extremely useful for parsing, and I also think that with some untraining and some practice you would find it easy to read and write.

    I have a new programmer- strong maths background, but no programming experience prior to K which she started about two weeks ago.

    Today, she's working on taking strings that look like this:

        y:"http://host/path/to.a.swf,http://host/path/to/b.swf"
    

    and finding out if the url-fragments are "claimed" by any any other user in a database, AND if the current user claims any url-fragments. So she has a database like this:

        d:`f`u!(("adap.tv";"adap.tv";"btrll.com";"btrll.com";"cbs.com";"cbsinter…
        l:?d`f
    

    and in about thirty minutes of puzzling came up with this:

        |/#:'y ss/:l[&~|/d.f[&x=d.u]~/:\:l]
    

    Since you don't know K I'll walk you through it:

        d.f[&x=d.u]~/:\:l
    

    This returns a list of bitmaps, such as:

        (10000000000000000b;00000100000000000b)
    

    What it's doing is taking all of the urls and indexing it by the where (&) address of each x (parameter to function: user id) is equal to the array of all of the users. That is, x=d.u returned: 01000001000000000000000000b and &x=d.u returned 1 7 (because the second and eighth element of that bitmap are ones). d.f[1 7] returns the second and eighth fragment.

    Then, she &~|/ which ors- the bitmaps (|/) together, finds their complement (~), and takes the where of (&) them, so in this case 0 5. l[0 5] then returns the strings in the master list.

    Note this is the list of all of the url fragments owned by other users:

        l[&~|/d.f[&x=d.u]~/:\:l]
    

    In PHP you might try to write:

        $mine = array();
        $theirs = array();
        foreach($db as $row) {
          if($row->u === $x) $mine[$row->f]=0;
          else $thiers[$row->f]=0;
        }
        $list = array_diff(array_keys($thiers),array_keys($mine));
    

    but there's a lot of syntax here, and a number of PHP function calls that a beginner might not be aware of. She's just using this:

        http://www.timestored.com/kdb-guides/files/kdb-cheat-sheet.pdf
    

    So then on to y ss/: which basically does a `strpos()` of each of our urls against the list we're scanning (i.e. the thing that looks like "http://url,http://otherurl". She then counts each (#:') result, takes the max again (|/). This means if ANY of those match, return `1b` otherwise return `0b`.

anonu 11 years ago

ive been using kdb+/q for over 5 years now - in a financial setting. I'd be happy to see the language go more "mainstream". There are definitely a lot of complaints about the terseness. There's no doubt, this adds to the steepness of the learning curve. But once you "see the light" you start realizing that you can do the same thing you do in perl or python in just 1 line in KDB. It makes more sense.

  • kbody 11 years ago

    I'm working on a algo-trading system and thinking of moving my tick data to kdb+, however I see no price on their site, care to enlight? Also, do you know what are the limits of the free evaluation/32-bit version? Thanks

    • beagle3 11 years ago

      32 bit version is 32 bit (databases limited to about 2GB per process, as are memory mappings). If that's good for you, use it.

      The 64-bit was, last I inquired (8 years ago or so) was in the "if you have to ask you can't afford it" oracle territory.

vizzah 11 years ago

Looks to me like the app itself (chat.htm) is missing from the repository?

  • srpeck 11 years ago

    Thanks, added.