Hacker News new | ask | show | jobs
by tempodox 4036 days ago
Nice to see an article that explains a bit about J's background. And definite sympathy points for the language supporting complex numbers. But I'm still wondering what the language's “high performance” is based upon. I'm an assembler hog and any language that doesn't compile to native code is just a toy to me. Yet the article only mentions an interpreter. I think, by now there must be something better than an interpreted write-only language.
5 comments

The code and the interpreter together are both so terse that they fit in the cache. That buys you a lot of speed.
IIRC the interpreter is thin as hell. Almost no syntax or interpretation overhead. Also the semantics of J makes it very mechanical sympathetic. Some kind of macros based wrappers to express loops.

ps: I'm not sure it was J .. maybe K. And I can't find the C source anymore. Haa...

pps: check this http://lambda-the-ultimate.org/node/5075 they discuss performance.

I post that!

I'm learning to build interpreters for a toy relational language (in F#). So a fast intepreter appeal to me.

I look at http://keiapl.org/rhui/remember.htm#incunabulum but a)I don't know C b)Don't know J so wonder if exist a easy-to-understand interpreter of J somewhere? The ones I look (in the link above) are very dense. Full of code-golf.

This is the kind of code I remember. I think someone tried to de-obfuscate it in an article.
Is it possible that you are referring to http://sblom.github.io/openj-core/ioj.htm ? I found it linked at http://lambda-the-ultimate.org/node/5075#comment-82793 .
I have try to find it with not luck. Any idea in how search for it?
> I'm an assembler hog and any language that doesn't compile to native code is just a toy to me.

First, what exactly is native code? Is it the PythonVM/JVM byte code? The x86 code it is JITted into? The microcode that interprets the "native" x86 code? You probably mean the x86/ARM/whatever bytecode, but that's not a trivial definition.

Practically speaking, compiling to "native code" is mostly useful given a known architecture. "rep movsb" used to be the fastest way to copy memory around; and then it was slow as mollasses; and then it was fast again. Table lookups were the fastest way to do 6-bit by 8-bit multiplications up until the 386 or 486 - and then the multiplier became faster than memory.

Somewhat surprisingly, J (and APL and K) tend to focus on promoting those things that have always been true - e.g. sequential access is much faster than non sequential; branch free code is better than branching code; small code/data that fit in cache/main memory is better than larger code/data that doesn't. The computation model fits modern CPUs and GPUs very well, despite being approximately the same one since the 1950s.

It's a different take on the "better algorithms beat faster implementations" - a good language that makes a good fast solution intuitive is often, in practice, better than one that can be faster with a lot of intricate work.

Let's say I create a new, interpreted language. It's called fgrep and it only has a couple instructions for searching text. But I spend 5 years optimizing those functions.

Now, if you need recursively search through a directory full of text files, would you use fgrep or would you write your own "high performance" search utility with a hard-coded (none of that slow run-time interpreting!) list of files and needle?

LtU discusses exactly the issue of how 'interpreted' can be faster: http://lambda-the-ultimate.org/node/5075 .