空间语言:以二维方式编写代码
Spatial languages: Writing code in 2D

原始链接: https://shukla.io/blog/2026-07/cccx.html

本文探讨了“空间编程”的概念,提出若代码能突破一维、从左至右的语法限制,将更具表现力。通过利用二维空间,开发者可以设计出直观的运算符(例如量子逻辑运算符),从而比传统串行代码更简洁地处理复杂的数据流、状态变更和临时变量(辅助位)。 作者通过模拟量子电路逻辑的“二维表达式”展示了这一构想,例如由“多数”(maj)和“非多数”(uma)运算符构建的三位加法器。这种空间布局实现了逻辑的简洁视觉化表达,并能自动管理临时变量的“清理”。 文章将这一理念与 Befunge、Orca、Racket 的 #2d 等二维编程语言以及随处可见的电子表格进行了对比。作者最终指出,我们目前对一维、从左至右代码的偏好并非技术上的必要性,而是受终端和键盘历史发展所限的认知偏差。通过挑战这些限制,程序员可以发展出更高效、更易读且更抽象的计算思维方式,这体现了“工具塑造思维过程”这一理念。

Hacker News 新动态 | 过往 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 空间语言:用二维方式编写代码 (shukla.io) 18 分 | BinRoo 发布于 1 小时前 | 隐藏 | 过往 | 收藏 | 2 条评论 | 帮助 cavoirom 34 分钟前 | 下一条 [-] 出于同样的精神,看看 Orca:https://100r.co/site/orca.html 它用于创作歌曲。你可以在链接页面看到演示。 回复 BinRoo 1 小时前 | 上一条 [-] 我最初是为了更好地阅读 Qiskit 代码而进行探索,结果带回了这个关于二维表达式的有趣想法。 回复 考虑申请 YC 2026 年秋季批次!申请截止日期为 7 月 27 日。 准则 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系 搜索:
相关文章

原文
Spatial languages: writing code in 2D

I guess expressions don’t really need to read left-to-right on a line.

Why can’t a < b be written vertically too?

a
<
b

All this time we’ve been writing expressions in 1D space, but what happens when we unlock an extra dimension?

Of course the IDE and parser need to play nicely for all this to work. Even then, what’s the point? Well, let’s take a look at these examples below.

3-arity functions

We don’t really see 3-arity functions written in infix notation much.

For example, in Python (and most other languages), you can and 3+ things at once:

Technically, that’s just composing multiple binary functions together.

Even this shortcut in Python to simplify (a < b) and (b < c) is more of the same thing:

Now, let me introduce you to a funny little operator I’ve been playing with called andFlip, which motivates the need for a true 3-arity infix notation. First, here’s the definition of the function:

uncomputing the intermediate t1 value within the same circuit is an important requirement.

Puzzle 2: reset the temporary variable back to the original value

If t1 starts off with an unknown boolean value n, then it gets more complicated.

t1 = n
t2 = 0

   t1    t2
(x @@ y) @@ z

The same trick above to reset t1 back to its original value won’t work.

See for yourself: when t1 = 1 and x, y, and z are all true, then t2 remains 0, which is incorrect.

t1 = 1
t2 = 0

(1 @@ 1) @@ 1
   t1    t2
(1 @@ 1)

So, what’s the answer?

Tada!

t1 = n
t2 = 0

   t1    t2
(x @@ y) @@ z
   t1    t2
(x @@ y) @@ z

Absolutely legendary. This single 2D expression resets t1 back to n while producing the correct result for t2.

This puzzle is inspired by the concept of resetting a borrowed ancilla in quantum computing. t1 is the “borrowed” or “dirty” value that remains unchanged.

Here’s the same circuit in Qiskit:

classic quantum ripple-carry adder, where the majority of (carry, bit, bit) is the next carry.

You may have noticed that maj leaves b and c dirty, holding a^b and a^c, the same kind of mess as our borrowed t1. To clean up, we’ll also introduce uma, the partner operator. The name comes from the same adder paper, “UnMajority and Add”: it un-majorities c, restores a, and adds the sum onto b:

c uma b        ((b @@ a) @ a) @ b
  a       :=        c

Let’s see what happens when we wire them up.

3-bit adder

We can build a 3-bit adder out of three majs that ripple the carry up through the a wires, with the final @ dropping the carry-out on c3, and finally one line of umas resetting all the scratch wires:

c0 = 0
c3 = 0

(b2 maj (b1 maj (b0 maj c0))) @ c3
    a2      a1      a0
((  .       uma b2) uma b1) uma b0
                            c0

That’s a full 3-bit adder in a single 2D expression that also cleans up after itself. The b wires now hold a + b, c3 holds the carry-out, and c0 and the a wires come back exactly as we found them. (Set c0 = 1 and you get a + b + 1 for free.)

Notice the two lines mirror each other. The top nests rightward down to b0 and ripples the carry back up; the bottom nests leftward down to b2 and unwinds back out. The shared a1 and a0 labels are the pivots, each serving the maj above it and the uma below it, and the . is a vertical pipe, standing for whatever wire sits directly above it, here a2. The carry chain is stitched together vertically: the uncompute touches the compute, just like in the puzzles.

Speedrunning other spatial languages

Here’s a quick tour of a few more spatial languages.

Befunge

The grandparent of 2D languages (Befunge, 1993): the instruction pointer physically travels the grid, and >v<^ steer it. Hello world bounces off the walls:

>              v
v"Hello World!"<
>:v
^,_@

Orca

Orca is a livecoding sequencer where every letter is an operator that reads its neighbors: A adds the value to its left and the value to its right, and writes the sum directly below itself. Sound familiar?

1A2
.3.

Racket #2d

A real, shipping language extension: Racket’s #2dcond is a cond evaluated in two dimensions. The left column tests b, the top row tests a, and the cell where both are true runs.

#lang 2d racket

(require 2d/cond)

(define (same? a b)
  #2dcond
  ╔═════════════╦═══════════════════════╦═════════════╗
  ║             ║       (pair? a)       ║ (number? a) ║
  ╠═════════════╬═══════════════════════╬═════════════╣
  ║ (pair? b)   ║ (and (same? (car a)   ║     #f      ║
  ║             ║             (car b))  ║             ║
  ║             ║      (same? (cdr a)   ║             ║
  ║             ║             (cdr b))) ║             ║
  ╠═════════════╬═══════════════════════╬═════════════╣
  ║ (number? b) ║          #f           ║   (= a b)   ║
  ╚═════════════╩═══════════════════════╩═════════════╝)

Hexagony

Hexagony runs on a pointy-topped hexagonal grid, like a certain background you may have noticed. Six instruction pointers start at the six corners. Hello world:

   H ; e ;
  l ; d ; *
 ; r ; o ; W
l ; ; o ; * 4
 3 3 ; @ . >
  ; 2 3 < \
   4 ; * /

Ladder logic

Ladder logic is how PLCs run factories (and, done properly, chicken coop doors): each rung is a relay circuit read rail-to-rail, and parallel branches are OR. This classic seal-in rung computes Run = (Start OR Run) AND (NOT Stop):

--+----[ ]--+----[\]----( )
  |   Start |   Stop    Run
  |         |
  +----[ ]--+
       Run

And an honorable mention for the most successful spatial language of all time: the spreadsheet, where every formula lives at a 2D coordinate and reads its neighbors.

“This Is Water”

If you know me, you know I love bringing up the Sapir-Whorf hypothesis, which proposes that language shapes the way you think:

  • Some Australian Aboriginal languages have no words for left and right, only compass directions, so their speakers always know which way north is.
  • Russian has two separate words for blue, so Russians are faster at telling two blues apart when the shades straddle that word boundary.
  • Haskell is purely functional, so you start recognizing monads everywhere you go. That sort of thing.

Likewise, I believe technology shapes which languages emerge.

  • A shell terminal forces us to write commands left-to-right, so we think of code horizontally instead of vertically.
  • Most keyboards are built for English and the standard ASCII symbols, so we think in those symbols :).

Being aware of our biases is a justified mental exercise, at least according to David Foster Wallace, who delivered a commencement speech titled This Is Water. Though his speech was less about ancilla uncomputation in quantum circuits and maybe more about growing up and being compassionate, you get the point. By challenging our habits, we can explore new ideas.

联系我们 contact @ memedata.com