[HN Gopher] J one-page interpreter fragment (1992)
___________________________________________________________________
J one-page interpreter fragment (1992)
Author : Tomte
Score : 56 points
Date : 2021-01-25 12:59 UTC (10 hours ago)
(HTM) web link (code.jsoftware.com)
(TXT) w3m dump (code.jsoftware.com)
| zserge wrote:
| Some time ago I've made a humble decoding of this wonderful code
| snippet: https://zserge.com/posts/j/
| daneelsan wrote:
| Thanks for this!
| daneelsan wrote:
| I don't get why the 5 in '5 + tr(...)'. t+r+d[3] is 5, I
| guess? The verb function should return an I and not an A.
| e->tokens in the wd function.
| bear8642 wrote:
| Indeed - was confused what elements of struct were on line 2.
|
| Thanks for explaining
| dang wrote:
| Discussed here: https://news.ycombinator.com/item?id=22831931
| userbinator wrote:
| Its density is many times higher than most C programs, but that's
| no big obstacle to understanding if you don't attempt to "skim"
| it; you need to read it character-by-character from top to
| bottom. It starts off defining some basic types, C for Character
| and I for Integer, and then the all-important Array. This is
| followed by some more shorthand for printf, return, and functions
| of one and two arguments, all of the array type. The DO macro is
| used to make iteration more concise.
|
| Then the function definitions begin. ma allocates an array of n
| integers (this code is hardcoded for a 32-bit system), mv is
| basically memcpy, tr (Total Rank?) is used to compute the total
| number of elements, and ga (Get/Generate Array) allocates an
| array.
|
| This is followed by the definitions of all the primitive
| operations (interestingly, find is empty), a few more globals,
| and then the main evaluator body. Lastly, main contains the REPL.
|
| While I don't think this style is suitable for most programmers,
| it's unfortunate that the industry seems to have gone towards the
| other extreme.
| maest wrote:
| Btw, this is considered more or less canonical k style. (with q
| being a slighty more readable version of this)
|
| It takes some time getting used to it, but, once you get the
| hang of it, going back to e.g. Python/Pandas is painful.
| wassenaar10 wrote:
| Somehow still more readable than actual J code
| avmich wrote:
| Unlikely. The point of writing C in this manner was to bring C
| closer to APL - or J, which was an evolution of APL at the
| time. So that J interpreter would be written in a form of J
| language. J language itself doesn't need to satisfy also C
| syntax, so J code is somewhat easier.
| KMnO4 wrote:
| The repository[0] for J is just as unreadable (albeit with
| slightly more white space). I don't know how a project is managed
| like this. Even the file names look obfuscated.
|
| [0]: https://github.com/tavmem/j
| jpfr wrote:
| That is pretty readable C... for developers from that
| particular community.
|
| The ngn/k implementation of the k language [1] is even more
| terse.
|
| [1] https://git.sr.ht/~ngn/k/tree
| sndean wrote:
| I think this is the main J repo [0]. (Though I'm not sure if
| it's any more readable.) Possibly interesting that Tavmem is
| the maintainer of Kona (open source K3/4). I guess he's
| comfortable with all APL/J/K languages.
|
| [0] https://github.com/jsoftware/jsource
| geocar wrote:
| > The repository[0] for J is just as unreadable
|
| People who can read this find it readable.
|
| I think it's a mistake to think that because you can't read the
| code, that it is the _code_ that is somehow unreadable, instead
| of a language you simply haven 't learned to read.
|
| > I don't know how a project is managed like this.
|
| It's not dissimilar to working with any proprietary programming
| language: You have to learn how to read and write this
| language.
|
| The fact that we can use an existing language's compiler can be
| confusing to people who don't know that language very well, but
| if you approach it from the perspective of a new (proprietary)
| language, using an existing language's compiler can be a great
| way to leverage the benefits of that existing language.
| MontyCarloHall wrote:
| >People who can read this find it readable.
|
| > I think it's a mistake to think that because you can't read
| the code, that it is the code that is somehow unreadable,
| instead of a language you simply haven't learned to read.
|
| The same could be said about Brainfuck. With enough effort
| people can learn to read almost anything; that doesn't mean
| that everything is equally readable.
| bidirectional wrote:
| Brainfuck is so simple that it is trivial to read. The
| problem there is a semantic one rather than a syntactic
| one, you cannot build any abstractions. J-style C has all
| the semantic expressiveness of C, and chooses a terse, but
| fairly uniform style.
| AshamedCaptain wrote:
| > I think it's a mistake to think that because you can't read
| the code, that it is the code that is somehow unreadable,
| instead of a language you simply haven't learned to read.
|
| This argument is significantly weakened when simply removing
| the meaningless macros and adding whitespace improves
| readability.
|
| It's not like it is complicated because it is written in a
| structurally different language, nor will you actually
| leverage any benefit from learning this language. It's just
| obfuscated under the guise of abbreviation.
| avmich wrote:
| > This argument is significantly weakened when simply
| removing the meaningless macros and adding whitespace
| improves readability.
|
| Yes, but for this case adding whitespace actually decreases
| readability. At least if you know Whitney's hate of
| scrolling.
| geocar wrote:
| > This argument is significantly weakened when simply
| removing the meaningless macros and adding whitespace
| improves readability.
|
| I disagree wholeheartedly. Whitespace tends to move code
| further away from the code that uses it; scrolling and tab-
| flipping requires the developer hold that code _in their
| head_ where it is most likely to degrade. It is much _much_
| better to make them remember as little as possible.
|
| It also helps reuse: If you don't scroll, you can see more
| code, so you can see if something is a good candidate for
| abstracting, just because you can _see_ them doing the same
| thing.
|
| Macros like this help with that, and so they aren't
| "meaningless". Less whitespace helps with that, and so it
| actually improves readability (to those who have to read
| it!).
|
| The trade-off is that you can't hire someone with "C" on
| their CV and expect them to be productive on their first
| day, but in a complex codebase, this might not be possible
| for other reasons.
| lihaoyi wrote:
| While this example is pretty dense, a "one page programming
| language interpreter" doesn't need to be so impenetrable. Here's
| a one-page (67 line) interpreter for a subset of the Jsonnet
| programming language, implemented in Scala:
|
| - https://github.com/handsonscala/handsonscala/blob/v1/example...
|
| From the top down, that snippet contains an AST definition, a
| parser, an object model, an evaluator, and an output serializer.
| This 67-line programming language interpreter is one of the
| projects in my book https://www.handsonscala.com/ (chapter 20),
| and while this example is minimal the same techniques were used
| for my production-ready Sjsonnet interpreter
| avisaven wrote:
| I actually used this as inspiration for a little self-challenge
| to write a programming language in 24hrs not too long ago [1]. I
| didn't get quite as far as I'd've liked to, but nonetheless if
| you have some time to kill, it was an extremely fun task to
| tackle.
|
| [1] https://github.com/block8437/afternoon-lang
| dang wrote:
| If curious see also
|
| 2017 https://news.ycombinator.com/item?id=14463874
|
| 2016 (one comment): https://news.ycombinator.com/item?id=12654054
|
| 2014 https://news.ycombinator.com/item?id=8533843
|
| Related from last year:
| https://news.ycombinator.com/item?id=22831931
|
| I'm pretty sure there have been other threads about this,
| probably via different articles.
| skruger wrote:
| A good walk-through of this code is here:
| https://rickyhan.com/jekyll/update/2020/01/16/j-incunabulum-...
| danmg wrote:
| It leaks memory on every line it evaluates.
| avmich wrote:
| I'm sure memory management was left to deal with later. In
| Roger Hui variant, memory leaks were eliminated early on, on a
| systemic level.
| MontyCarloHall wrote:
| I guess freeing all those pointers returned by ma() would be
| too verbose.
|
| Seriously though, this must have been a deliberate design
| decision? Arthur Whitney is no amateur.
| DaiPlusPlus wrote:
| Question: where/how are the `mv` and `pr` functions defined? And
| how does this even compile when it's using `gets` without
| `#include <stdio.h>` ?
|
| I do see it's using the `implicit int` rule though.
| naters wrote:
| `mv` is defined on the same line as `ma` is, right after the
| five `#define`s.
|
| `pr` is on the last line before the only line break.
|
| It's a pretty dense program to walk through, but not as
| completely impenetrable as I first thought after taking some
| time and making notes as I went.
| userbinator wrote:
| This is pre-C89, K&R C.
| jonjacky wrote:
| Here is a recent C program in a similar compressed style, a
| Scheme compiler:
|
| https://c9x.me/qscm/data/qscm.c
|
| via this page which was recently linked on HN:
|
| https://c9x.me/qscm/
| eimrine wrote:
| Is there any Lisp interpretation on J language? I have hard time
| searching anything called with one letter only.
| rscho wrote:
| Anyways, info about J can pretty much be found only on its
| website (jsoftware.com), so don't really bother looking
| elsewhere. The only other good place is Rosettacode.
|
| What do you mean by "Lisp interpretation on J language"?
|
| There's an APL in Common Lisp called April. Otherwise, there's
| an unfinished J interpreter on the Racket package manager.
| eimrine wrote:
| Sorry for incorrectness, I want to look at interpreter of any
| dialect of Lisp language, written in J, if the one exists. I
| found J's approach to syntax interesting to explore.
| kd0amg wrote:
| Writing a lisp interpreter in J won't really do more to
| help explore J's syntax than writing anything else in J. It
| might be a good way to explore how J handles tree-like
| data, but that's not really something J is designed to do
| well (if you _really_ want to use an array-oriented
| language for tree processing, Aaron Hsu 's dissertation
| covers a range of techniques that are more scalable than
| the naive nest-of-short-boxed-vectors approach typically
| used in J).
| rscho wrote:
| What people often miss with J is how good it is for exploratory
| programming due to its terseness and most importantly its
| integrated columnar store. It replaced R for data wrangling in my
| stats programs, and relegated it to just running the models.
|
| Once you get used to it, it's really a breeze and far easier to
| modify than 500+ sloc R scripts.
|
| Of course, that does not work for everyone, and especially not
| for big teams, but still!
| vmchale wrote:
| > It replaced R for data wrangling in my stats programs
|
| Do you find it faster?
|
| I have good experiences with J due to its terseness, but I'm
| curious why scientists still use R/Python - is it just inertia?
| Libraries/FFI?
| rscho wrote:
| Faster to program yes, massively so. Faster to execute, it
| depends on what I'm doing, but it's never a problem for me as
| my data is usually pretty small and quite messy. It doesn't
| feel slow at all, at least. And obviously if you're doing
| arrays you'll certainly not run faster in Python/R.
|
| As for R/Python it's mostly familiarity with the notation
| (especially for python) and established popularity, with a
| large ecosystem as a consequence.
|
| I mean, as a beginner in Python it just works (slowly). As a
| beginner in J, you cry... The interesting distinction is that
| Python/R APIs can be quite convoluted and the rug may be
| pulled from under you without warning, while in J you learn
| the primitives and you're off to the races. Also, J is much
| faster for its use case and avoids the need to write C in
| most cases where using it is relevant.
| up2isomorphism wrote:
| I want to point out the large part of "unreadability" feeling
| here comes from the fact the code is pre-ANSI C89. so tr(r,d)I
| _d;{I z=1;DO(r,z=z_ d[i]);R z;} is just a function definition.
|
| I would say the structurally this extremely easy to read
| considering there is zero comments and the way it is presented.
| One can make this readability obvious by just expand the macros,
| change indentations and add line breaks, or, you can just spend
| several days to "get used" to it like Roger Hui (and Arthur who
| just use this kind of style for life).
___________________________________________________________________
(page generated 2021-01-25 23:02 UTC)