Ray Tracing in J
12 comments
·May 28, 2025gcanyon
dfboyd
"[verbs] get forked and hooked until you go insane trying to track it all"
J comes with a Qt IDE, which has a function "dissect" that displays a graphical parse tree of an expression.
load 'debug/dissect'
dissect '(+/ % #) ? 10 $ 100'
gcanyon
Thanks! I haven't touched J in about ten years -- and I never used dissect -- and I never did anything serious in it, just about thirty project euler problems for fun.
anthk
That should have an ASCII art alternative too.
Vox_Leone
Fascinating article – a great example of J's array-processing power for concise, performant geometric computation.
It got me thinking about how different paradigms could complement this. I've been working on a Python project[0], which is a framework for quaternion-driven traversal of tree-like structures based on orientation rather than just position or order.
Essentially, J handles the low-level "how" of vector math at scale, while SpinStep-like concepts could provide a higher-level, more semantic "what" and "why" for decisions driven by explicit orientation sets and angular relationships.
It's an interesting thought experiment on combining the raw power of array languages for geometry with more specialized frameworks for orientation-based reasoning.
magicalhippo
Bit disappointed it wasn't a re-implementation of SmallPT[1].
Would have been interesting to see it deal with multiple different objects with different materials, the recursion and such.
Guess it shouldn't take that much to turn it into something like SmallPT.
curtisszmania
[dead]
bobsmooth
Could someone write a script to find out how many times "<problem> in <single letter>" has been posted to HN?
MangoToupe
Yea but ray tracing is super fun. It's hard to be irritated with fun.
pasquinelli
what if i write one in J and then post it on HN?
libraryatnight
It'll make front page, and I'll follow it up with a blog post about why it changed my life to rewrite it in K.
ThrowawayTestr
Only if it counts itself
A few important bits this left out (as far as I read, which wasn't too far). Note: I am not a J expert, just a dabbler.
J's tacit syntax can generally transparently take either a single argument on the right, or two arguments, one on the left and one on the right.
In addition to the fork described in the article, J defines a "Hook" for two verbs (instead of the fork's three). A hook applies the right verb to the right argument, then applies the left verb with the original argument on the left and the result from the right verb on the right. Meaning:
J allows arbitrarily long strings of verbs: these get forked and hooked until you go insane trying to track it all in your brain.Defining a function longer than a fork and using the same code inline can (often?) not give the same results. I think that's why the caps are needed in the magnitude function in the article.
I think the article is missing a trick on the magnitude-of-a-vector bit: J has a marvelous conjunction called "under" which, when applied to two verbs, first applies the first (right) verb, then applies the second verb to the result, and then unapplies the first verb.
So when you have the need to "sqrt the sum of the squares" you should immediately be noticing that sqrt and square are opposites, and be thinking "under".
So magnitude can be expressed more succinctly (and I think more idiomatically, but again I'm not an expert) as:magnitude =: +/&.:*:
magnitude 3 4
magnitude 3 4 5