20 种有趣、独特且滑稽的编程语言

2025-06-04

20 种有趣、独特且滑稽的编程语言

“小心那只杰巴沃克,我的孩子!
它有咬人的下巴,有抓人的爪子!
小心那只贾布贾布鸟,还有,躲开
那只臭名昭著的班德斯奈奇!”

——刘易斯·卡罗尔


尽管有时感觉如此,但编程语言通常旨在让我们的生活更轻松。例如,在 Java 中表达类之间的复杂关系、数据边界检查以及与用户的交互比在CPU 操作码中要容易得多(而且只是稍微简洁一些)。

但有些语言设计者另有目的。一门编程语言的设计初衷可能是简化数据矢量化、简化多线程或提升性能。而有些语言的设计初衷是,唯一的关键字就是chicken……不同的笔触。

以下是我精心挑选的 20 种有趣、优美、甚至让人眼花缭乱的编程语言。虽然大多数都被认为是“深奥的”,但其中一些实际上被一些资深程序员日常使用。看看你能不能分辨出哪些是,哪些是。


目录

  1. 脑残
  2. 合法的
  3. 玛尔博格
  4. APL
  5. (D♭、D♭♭ 和)Velato
  6. 皮特
  7. 空格
  8. 内卡
  9. 一元运算符除外,每个零都替换为该编程语言的名称,或者,替换为哥德巴赫猜想的最小反例。编译器和解释器只需实现前一种选项。
  10. 种子(和 Befunge)
  11. LISP
  12. 功能
  13. ///
  14. 工厂
  15. 高尔夫语言
  16. 具有二维源代码的语言
  17. 强调源代码美学的语言
  18. 构建的语言使得源代码看起来像___
  19. 问#

#1.脑力激荡

在线翻译

相关: Unibrain

Brainfuck(有时也写成 brainf___、brainf***,或者简称为 BF)是深奥编程语言( esolangs )的典型代表。用 BF 打印“hello world”的程序如下所示:

+[-[<<[+[--->]-[<<<]]]>>>-]>-.---.>..>.<<<<-.<+.>>>>>.>.<<.<-.
Enter fullscreen mode Exit fullscreen mode

Brainfuck 是一种基于磁带的语言。你可以将磁带语言中的程序想象成一个极长的一维数组,初始值为零。磁带的一端有一个指针,可以向前或向后移动,每次移动一个存储单元。存储单元中的值可以递增或递减(限制为整数值),并且有括号允许循环。

BF 语言规范中有八个命令。指针当前指向的单元格称为“当前单元格”:

>  move the pointer one cell to the right
<  move the pointer one cell to the left
+  increment the value in the current cell
-  decrement the value in the current cell
.  output the character represented by the value in this cell
,  input a character and store it in the cell at the pointer
[  jump past the next ] if the cell under the pointer is zero
]  jump back to the most recent [ if the cell under the pointer is nonzero
Enter fullscreen mode Exit fullscreen mode

就是这样!在 Brainfuck 程序中出现的任何其他字符都会被视为注释并被忽略。Brainfuck 是图灵完备的,因此理论上它可以执行任何其他编程语言可以执行的计算任务,尽管用 BF 编写它可能需要更多时间。

Brainfuck 启发了无数的模仿语言,包括:

  • ( ͡° ͜ʖ ͡°)fuck——类似于 brainfuck,但命令全部被Lenny 的表情取代
  • Bodyfuck ——Brainfuck 的手势解释器
  • 我真的很讨厌你的 bf 衍生语言——一种与 BF 具有相同字符集的语言,但其中所有字符都有不同的含义;旨在挫败 BF 爱好者
  • JSFuck —— JavaScript 的一个“深奥子集”,它只使用字符+!()[]创建类似 BF 的语法,其中“Hello, World!”程序需要超过 10,000 个源代码字符
  • TreeHugger ——BF 的衍生产品,它使用无限二叉树数据结构,而不是无限磁带
  • POGAACK ——BF / Chicken 交叉

[返回目录]

2.鸡肉

Chicken 可能是最著名的单关键字语言,尽管从技术上讲,基于堆栈的 Chicken 语言中有 11 条指令,对应于 11 个操作码,编号为 0 到 10。

Chicken 的灵感来自于Doug Zongker 撰写的一篇论文,旨在嘲笑难以理解的学术演讲

操作码编号给出了关键字必须出现的次数(#下表给出)chicken(以空格分隔)以表示该特定指令:

# 命令
0 停止执行
1 将字符串“chicken”压入堆栈
2 将堆栈顶部的两个值相加
3 从堆栈中减去顶部两个值
4 将堆栈顶部的两个值相乘
5 比较堆栈顶部的两个值是否相等,将“真”或“假”结果推送到堆栈
6 双倍宽度指令。下一条指令指示要加载的源。0 表示从堆栈加载,1 表示从用户输入加载。栈顶指向要加载到堆栈的地址/索引。
7 栈顶指向要存储的地址/索引。低于该值的值将被弹出并存储。
8 栈顶是跳转目标的相对偏移量。栈底的值是条件。只有当条件为真时才会跳转。
9 将堆栈顶部的值解释为 ASCII 并推送相应的字符
10+n 将文字数字推送到n-10堆栈上。

当程序停止时,堆栈上的任何内容都会打印到屏幕上(这在为代码高尔夫设计的语言中很常见)。这意味着用该语言创建一个自我复制的quine程序相当容易:

chicken
Enter fullscreen mode Exit fullscreen mode

由于关键字chicken在第一行出现一次,字符串“chicken”被压入堆栈。然后程序到达末尾,堆栈(仅包含单词“chicken”)被打印到屏幕上。该程序准确地复制了其自身的源代码。这在大多数语言中都很难做到,不过 Mame(本名 Yusuke Endoh)创造了这个绝对疯狂的奎因中继器,它可以循环切换 100 种不同的编程语言,每种语言都会输出下一种语言的源代码。(说真的,去 GitHub 上看看他们的一些项目吧,他们太疯狂了。)

[返回目录]

#3.合法

相关: Dirst

Legit(发音为硬“g”)是一种图灵完备的编程语言,其中程序“完全由Git存储库中的提交图定义”。存储库本身的内容被完全忽略。

合法指令被编码在 Git 仓库的提交信息中。执行过程通常从提交到其父提交(沿着命令的输出向下git log --graph --oneline移动)。如果一个提交有多个父提交,它们会形成一个命令栈,索引从 0(最老的提交)开始,栈顶会被弹出,值必须是与正确的父提交索引对应的数字。不过,可以使用goto类似 - 的命令来控制程序流程,这些命令可以跳转到特定的提交。

合法的“Hello World!”程序如下所示:

$ git log --graph --oneline
*   b63fd70 (HEAD -> master, origin/master, origin/HEAD) Merge pull request #1 from rohieb/master
|\  
| *   1f44c51 0
| |\  
| |/  
|/|   
* | b9e1e95 "Hello world\n"
| * fbb02fe "Hello world!\n"
|/  
*   8013037 (tag: reverse-loop) dup
|\  
| * 6883822 write 1 left [reverse-loop]
*   e0a4d04 (tag: print-loop) 1 right read dup
|\  
| * d646ef4 put [print-loop]
* 25a3a62 quit
Enter fullscreen mode Exit fullscreen mode

请注意,有两行代码写着“Hello World”,第二行代码末尾添加了一个“!”。该语言的创建者编写了这个程序,然后为该更改合并了一个 PR。由于合法程序本身就是 Git 仓库,因此合法程序本身不存在版本控制,至少 Git 本身不存在版本控制。这意味着随着更改的进行,程序最终可能会看起来很混乱。

该语言的创建者 Sebastian Morr 曾讨论过编写合法程序有多么困难:

说实话:我厌倦了手动编写 Git 命令来创建合法的程序。自上而下执行的一个后果是,你必须倒着写程序,每次我打错一个字,就得从头开始,因为之前的提交都会失效。所以……我开始编写 Shell 脚本,然后用它来生成合法的程序。

尽管如此,他还是设法用 legit 写了一个 brainfuck 解释器,间接证明了 legit 是图灵完备的。Morr 对他的语言使用者的挑战是什么?写一个 legit quine:

“编写一个合法的程序,打印创建自身所需的 Git 命令!祝你好运。”

[返回目录]

#4.玛尔博吉

在线翻译

Malbolge 以但丁《神曲》中第八层地狱命名,是一种专门设计成几乎不可能使用的语言。Malbolge 程序使用三进制运算(因此是三进制运算而非运算),会篡改和加密自身的源代码,并且容易受到实现和规范中 bug 特性的破坏。

Malbolge 的创建者 Ben Olmstead 表示,如果他能让这种语言变得更难编写代码,他会

我知道文档中记录的表格和实现的表格之间存在不匹配。我注意到,有些人认为错误出在规范中,而另一些人则认为错误出在实现中;这无疑使 Malbolge 更难使用,并分裂了用户社区(至少目前是这样)。

“如果我要制作 Malbolge 2000,我肯定会让文档出现微妙的错误。”

Malbolge 语言的编写难度极高,甚至连 Olmstead 都从未用它编写过程序,除了“一个打印‘H’并退出的程序”。第一个 Malbolge 的“Hello, World!”并非由语言编写,而是在该语言发布八年后,通过一个定向搜索算法发现的。该算法探索了所有可能的 Malbolge 程序空间,直到找到一个能够产生正确输出的程序。

以下是 Malbolge 中的一个示例“Hello World!”程序:

(=<`#9]~6ZY32Vx/4Rs+0No-&Jk)"Fh}|Bcy?`=*z]Kw%oG4UUS0/@-ejc(:'8dc
Enter fullscreen mode Exit fullscreen mode

怪异语言收藏家瑞安·库斯纳里(Ryan Kusnery)曾宣称:“有一天,有人用 Malbolge 语言写出一个程序,能简单地将输入复制到输出,那一天,我的头发就会瞬间变绿。那一天,大象会变成紫色,骆驼会飞翔,牛也能穿过针眼。”

尽管 Kusnery 确信这样的程序不可能实现,但专业的深奥程序员 Matthias Lutter 还是成功编写了一个 Malbolge quine,尽管代码超过 800 行,但它确实能够准确地输出其源代码(如果您有大约一个小时的时间可以浪费,请在这里尝试一下)。

[返回目录]

#5. APL

我认为编程语言(APL)是我遇到过的最令人印象深刻的深奥语言之一(如果可以这么称呼的话),主要是因为它比这个列表中的大多数其他语言早存在了几十年。

APL 时代仅有的其他主要语言是COBOLLISPFORTRANALGOL,后者是 C 语言家族的精神先驱。

APL由 Kenneth Iverson 于 20 世纪 60 年代初创建,其主要目标是提供对数组、矩阵和高维数据结构的简单、简洁的操作。矩阵操作在数学、物理和计算密集型科学领域中很常见。提供一种创建和操作这些数据结构的简便方法,理论上应该能减轻科学家的工作负担。

当然,多维数组的操作在这些领域仍然至关重要,因此MATLAB、Wolfram 语言和 R等现代语言都从 APL 中汲取了许多灵感。这些更现代的语言与 APL 之间最大的区别在于 APL 的字符集。

在类似 ALGOL(类似 C)的语言中,您可以定义如下数字数组:

int array[] = { 1, 2, 3, 4, 5, 6 };
Enter fullscreen mode Exit fullscreen mode

在 APL 中,这看起来像

array ← ⍳6
Enter fullscreen mode Exit fullscreen mode

向左的箭头用于赋值,iota 字符用于创建一个从1到的整数数组N,其中N是字符后面的数字

APL 引入了各种各样不常见的字符,它们执行不同的功能。这样做可以使代码本身保持非常紧凑,但通常会牺牲可读性(对于习惯使用 ALGOL、FORTRAN、COBOL 或 LISP 等语言的程序员来说)。以下 C 代码:

int arr[] = { 4, 5, 6, 7 };
int len = sizeof(arr)/sizeof(arr[0]);
int sum = 0;

for (int ii = 0; ii < len; ++ii)
  sum += arr[ii];
Enter fullscreen mode Exit fullscreen mode

...可以使用 APL 进行大幅压缩:

sum ← +/(3+⍳4)
Enter fullscreen mode Exit fullscreen mode

APL 使用向量化运算,将 添加3到由 创建的数组的每个元素上⍳4。例如,⍳4创建数组[1, 2, 3, 4],并将3+⍳4添加3到该数组的每个元素上,得到[4, 5, 6, 7]。然后,“sum over”运算符+/将该数组的元素相加,4 + 5 + 6 + 7得到22,并sum通过向左的箭头将其赋值给 。

我希望以上解释能让您稍微了解一下 APL 的功能。一些现代语言(例如 R)大量使用向量化运算,这可以使数据操作变得非常轻松简洁,但确实需要一些时间来适应。

APL 大师们可以仅使用几十个字符(尽管其中许多是 APL 特有的字符)编写极其复​​杂的程序。为了方便您的欣赏/解答您的困惑,以下是约翰·康威的《生命游戏》全文,是用Dyalog APL(APL 的一种现代方言)编写的:

life ← {↑1 ⍵∨.∧3 4=+/,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵}
Enter fullscreen mode Exit fullscreen mode

如果有人能在评论中一步一步地向我解释这一点,我会非常感动。

[返回目录]

#6。 (D♭、D♭♭ 和) Velato

相关: Choon音符

D♭(发音为“dee flat”,像音符一样)和D♭♭(“dee double flat”)是玩笑语言,据我所知从未真正实现过。这很遗憾,因为 D♭ 原本应该为 C# 语言提供“一些细微关键的改进”,包括:

  • LowerClass和对象MiddleClassUpperClass根据它们可以拥有的属性以及它们与其他Class实体允许的交互来区分。UpperClass实体可以friends通过成为Lobby,例如:

    UpperClass BigShotRepublican
    {
      Investments portfolio;
      Yacht coasts[6];
      Lobby<Politicians> inPocket;
    }
    
  • 更加“直观”的异常处理,添加了新的关键字throwUpupChuckpukeralphhurl。正如语言文档所述:

    bucket这些传达了不同级别的异常严重性,您的应用程序可以使用它来确定捕获异常所需的大小...有时bucket可能会溢出,因此您需要堆叠bucket以便它们捕获溢出。

  • 新的泛型,包括Hash、、。根据文档,“所有泛型都在命名空间中处理” Pot并且可以“加速应用程序的性能”和“增强最终用户体验”,但应适度使用。CokeCrystalStreetCorner.Pharmacy

虽然 D♭ 会在 C# 语言上提供这些(以及更多)改进,但D♭♭也会提供(大概)比 C 语言类似的优势。

Velato是另一种音乐语言,尽管它与 D♭ 和 D♭♭ 的不同之处在于它实际上已经实现。Velato 源代码以MIDI文件的形式编写——音符的音高和顺序决定了程序的操作。

程序的第一个音符是“根音”,可以通过演奏根音大二度音程的音符来改变它。其他音程和音符组合决定了其他操作;例如,模运算符的%编码方式是先演奏根音的五度音符,然后再演奏五度音符,最后演奏六度音符。

Velato 中的一个示例“Hello, World!”程序可能如下所示:

听这里!

虽然并发(“堆叠”)音符的顺序确实会影响程序的运行,但仅凭乐谱无法完全描述 Velato 程序。

[返回目录]

#7.皮特

相关: Skastic

另一种艺术深奥语言是 Piet,以荷兰画家皮特·蒙德里安 (Piet Mondrian)的名字命名,他以其由简单几何形状组成的抽象艺术而闻名:

皮特·蒙德里安 1930 年的艺术作品,

Piet 程序以像素的形式“写入”位图文件中,包含 6 种不同色相的 3 种深浅色调,以及白色和黑色,总共 20 种不同的颜色。这些“彩色”颜色(除白色和黑色外的所有颜色)排列成一个圆环,从基色到其“暗”色相,再到其“亮”色相,再回到基色相,都被视为朝同一方向(正方向)移动。同样,从红色 -> 黄色 -> 绿色 -> 青色 -> 蓝色 -> 洋红色 -> 红色 ->……的移动也是循环的,并且是正方向的。

程序启动时,Piet 从图像的左上角开始“读取”位图中像素的颜色。执行过程从左向右进行,直到遇到一堵黑色像素的“墙”。此时,程序执行的方向会改变,像素会从上向下读取(始终通过顺时针旋转 90 度来改变方向)。画布的边缘也被视为“黑色像素”。

彩色区域之间的过渡编码了程序的操作。例如,如果我们在图像上移动时将色调“旋转”一个单位(例如从红色->黄色),则编码为“加”操作。如果我们也将“亮度”改变一个单位(例如从红色->深黄色),则编码为“减”操作。移入或移出白色区域不编码任何操作,并且是在不执行任何操作的情况下改变颜色的唯一方法(这在循环中很有用)。

因为程序只依赖于颜色之间的过渡,而不是颜色本身,也不依赖于在“画布”上移动的方向,所以程序可以非常简单,也可以非常“艺术化”。例如,下面这个程序从用户那里获取一个数字,计算它的平方,然后打印出这个平方值

Piet 中的一个简单程序

...这是同一个程序,稍微改进了一下

同一个程序,看起来更漂亮一点

我见过的最好的 Piet 程序之一就是这个,它打印“Piet”

Piet 中一个非常漂亮的程序

现在我们只需要有人将 Piet 和 Velato 结合起来,创建一种在多媒体文件中对程序进行编码的语言。

[返回目录]

#8.空白

相关: 痛苦

在编程语言中,空白字符(空格、换行符、制表符等)的重要性各不相同。有些语言不太在意,有些则非常在意(例如 Python),还有至少有一种语言在意空白字符。这种语言被命名为——颇具创意——“Whitespace”。

所有可见字符(数字、字母、标点符号等)都会被空白忽略。事实上,大多数空白字符也会被空白忽略。空格(ASCII 32)、制表符 (ASCII 9) 和换行符 (ASCII 10)是空白程序中唯一有意义的字符。

Whitespace 中的“Hello, world!”程序如下所示(“点”.添加到每行末尾,因此此浏览器中不会删除“尾随空格”):

           .
    .
                    .
    .
                      .
    .
                      .
    .
                            .
    .
                  .
    .
             .
    .
                        .
    .
                            .
    .
                     .
    .
                      .
    .
                  .
    .
                .
    .
  .


Enter fullscreen mode Exit fullscreen mode

(您可以单击并拖动以突出显示上述代码中的空格和制表符。或者在此 Web REPL中尝试一下。)

空格代码每次只写一个命令,其中制表符、空格和换行符的特定序列表示特定类别的命令——I/O、堆栈操作、算术。选择类别后,将使用另一个制表符、空格和换行符序列来选择该类别中的特定命令。所有数字均采用二进制编码(空格 = 0,制表符 = 1),所有字符均由其 ASCII 索引表示(同样采用二进制编码,因此制表符-空格-空格-空格-空格-制表符-制表符 为100001167C)。

各种各样的程序都是用空格编写的,包括quinesBrainfuck 解释器等等。当然,一些空格程序也隐藏在其他语言的源代码中。这些多语言程序可以作为空格代码运行(所有可见字符都会被忽略),也可以作为“宿主”语言的代码运行,前提是隐藏的空格程序所需的空格不重要。

以防万一你需要担心另一件事。

[返回目录]

#9. INTERCAL

INTERCAL 是“没有可发音首字母缩略词的编译器语言”的缩写,可以说是有史以来第一种深奥的语言。

“……1972 年,普林斯顿大学两名学生唐·伍兹 (Don Woods) 和詹姆斯·M·里昂 (James M. Lyon) 创作了一部戏仿作品……[INTERCAL] 讽刺了当时各种编程语言的某些方面,以及 20 世纪 60 年代提出的各种语言结构和符号的激增。” [来源]

INTERCAL 的设计初衷就是让人困惑,难以使用。常见的符号被毫无意义地重命名(例如, 'is a "spark"、"is "rabbit ear"、:is a "twospot" 等等),数字只能通过逐个拼写来输入(例如,TWO FIVE SIXis the number 256),而且一个未记录的“特性”意味着程序可能会因为不礼貌(关键字使用PLEASE不足)或过于礼貌(使用PLEASE过多)而被编译器拒绝。

维基百科提供了这段来自 INTERCAL 参考手册的精彩引文

一个众所周知且屡见不鲜的事实是,一个工作成果难以理解的人往往备受尊敬。例如,假设有人说,将 65536 存储在 32 位 INTERCAL 变量中的最简单方法是:

DO :1 <- #0¢#256
Enter fullscreen mode Exit fullscreen mode

任何理智的程序员都会觉得这太荒谬了。这确实是最简单的方法,程序员会在老板面前出丑,而老板当然会碰巧出现,老板们通常都会这么做。即使程序员是正确的,其后果也同样毁灭性。

不过,INTERCAL 是一种非常宽容的语言。任何 INTERCAL 编译器ick无法理解的代码都会被忽略。这意味着所有 INTERCAL 程序从定义上来说都是没有 bug 的!这很好,因为最初的 INTERCAL 是为EBCDIC字符集编写的,但后来的版本迁移到了 ASCII。因此,INTERCAL 的不同方言拥有完全不同的指令集。

对于地球上想要让 INTERCAL 与 .NET 协同工作的 15 个人来说,你们很幸运 ——有人有足够的空闲时间来实现这一点

[返回目录]

#10.一元运算符 except 中的每个零都被替换成该编程语言的名称,或者,替换成哥德巴赫猜想的最小反例。编译器和解释器只需实现前一种方案

在上面关于brainfuck的部分中,我们只看到了数百种BF 衍生语言中的一小部分。虽然也有一些有趣的衍生语言,但我尽量不把它们都写进去,因为这样一来,这篇文章很快就会变得毫无意义。

不过,我想和大家分享一个来自脑洞世界的特殊胡说八道。它是一种叫做“一元语言”的小语言,只不过每个零都被替换成这种编程语言的名称,或者,或者,被替换成哥德巴赫猜想的最小反例。编译器和解释器只需实现前一种选项。(在本文的其余部分,我将上述语言称为“这种语言”。)

这种语言,顾名思义,是Unary编程语言的衍生品。Unary 的命令与 BF 相同,但它们采用一元数字系统编码——也就是说,该系统只有一个符号。在本例中,这个符号是0

一元系统听起来可能并不罕见,你几乎肯定遇到过。如果你曾经需要追踪手动投票,或者记录一系列游戏中的胜负,你可能用过计数符号。在这个系统中,一条直线代表1,两条直线代表2,依此类推。计数符号是一种一元数字系统。

在 Unary 中,brainfuck 命令使用下表以二进制进行编码:

brainfuck 命令 二进制索引
> 000
< 001
+ 010
- 011
100
101
[ 110
] 111

要编写一元程序,首先要编写一个 brainfuck 程序。例如,这是一个非常简单的 BF 程序,它只是将一个数字2与另一个数字相加3,然后将结果打印到终端:

++>+++[<+>-]++++++++[<++++++>-]<.
Enter fullscreen mode Exit fullscreen mode

在这里尝试一下!

在 Unary 中,我们首先将所有这些 BF 符号转换为它们的二进制等价物:

010010000010010010110001010000011111010010010010010010010010110001010010010010010010000011111001100
Enter fullscreen mode Exit fullscreen mode

...然后,我们1在这个非常大的二进制数前面加上 a:

1010010000010010010110001010000011111010010010010010010010010110001010010010010010010000011111001100
Enter fullscreen mode Exit fullscreen mode

最后,我们将这个数转换为一元数。Wolfram |Alpha告诉我,这个数等价于

812,443,533,011,490,965,255,226,984,396
Enter fullscreen mode Exit fullscreen mode

...以十进制表示(“大约 812 亿亿”),因此这个数字的一​​元表示就是那么多个0s,背靠背。

这种语言与一元语言的不同之处在于,这种语言0用以下任一方式替换每个字符:

哥德巴赫猜想(又称“哥德巴赫猜想”)指出

...每个大于 2 的偶数都可以表示为两个素数的和。[来源]

假设我们会0用最小的整数来替换每个数,这个最小整数(截至本文撰写时)的下限至少为4 * 10^18。然而,由于哥德巴赫猜想尚未被推翻,我们只能0用编程语言的名称来替换它们。幸运的是,“编译器和解释器只需实现前一种选项”。

即便如此,用这种语言编写的上述2+3程序仍然相当长,因为该编程语言的名称长达 238 个字符。用这种语言编码这个小程序大约需要十亿兆兆兆字节的磁盘空间。这种语言是宇宙中最不节省资源的语言的有力竞争者。

[返回目录]

#11.种子(和 Befunge)

Seed 与一种名为Befunge的早期 esolang 相关,Befunge 中的程序是在二维网格上编写的。在 Befunge 中,用户定义“箭头”指令来在程序中移动指针。例如,Befunge 中的“Hello, World!”可以这样写:

>              v
v  ,,,,,"Hello"<
>48*,          v
v,,,,,,"World!"<
>25*,@
Enter fullscreen mode Exit fullscreen mode

您可以看到> v、 和<字符,它们实际上指向代码应该被解释/编译的方向。(还有一个^字符这里没有用到。)

Befunge 的设计初衷就是为了提高编译难度。由于它可以从四个方向(从左到右、从右到左、从上到下或从下到上)中的任意一个方向执行,并且提供了自修改代码的功能,因此编译器很难推断 Befunge 的源代码。

Seed 把这种相对优雅(但绝对不寻常)的语言变得完全荒谬。Seed 程序只由两个数字组成:长度和随机种子。随机种子被输入到梅森旋转算法中,该算法用于生成指定长度的随机字符串。然后,Seed 会尝试将该随机字符串作为 Befunge 程序运行。就是这样。

Seed 是一种极其易于编程的语言——只需要两个数字——但由于其固有的随机性,它需要大量的资源。使用 Seed 进行编程通常意味着生成大量指定长度的随机程序,并根据期望输出检查程序输出。由于Befunge 程序中包含 96 个有效字符(ASCII 码为 32 到 126,另加换行符),因此96^n可能存在包含字符的 Befunge 程序n。因此,测试所有长度为 5 的有效程序需要生成并运行超过 80 亿个不同的 Befunge 程序。

尽管如此,一些爱好者还是设法编写了一些种子程序,它们确实能做一些有用的事情。例如,这个程序:

1 186
Enter fullscreen mode Exit fullscreen mode

...不执行任何操作并退出,而该程序:

4 80814037
Enter fullscreen mode Exit fullscreen mode

...打印字符'h'。由于可能的程序数量会随着程序长度的增加而呈指数级增长,因此编写一个“Hello World”程序极其困难。然而,esolang 爱好者Krzysztof Szewczyk仍然设法找到了一个仅使用 4151 位随机种子的解决方案。正如我所说,这很容易编程!

[返回目录]

#12. LISP

我对 LISP 了解得越多,就越喜欢它。LISP 于 1958 年首次发布,是至今仍在广泛使用的最古老的高级语言之一(仅比在科学界仍然流行的 FORTRAN 晚一年)。LISP 的全称是“列表处理器”(LISt Processor),本质上它的功能就是处理列表。

LISP 中的所有内容要么是原子,要么是列表。列表可以包含 原子 ,也可以包含其他列表。 原子是“不可分割的”,可以是数字、字符串等。例如,以下列表:

(1 "hey" (+ 7 x))
Enter fullscreen mode Exit fullscreen mode

...包含三个元素: 原子1、 原子"hey"和 列表(+ 7 x),其中包含其自己的三个元素。

请注意,LISP 中没有类型声明。原因有两个。首先,LISP 使用一种动态类型,可以检查原子是字符串还是数字,并且如果程序员尝试编写一些奇怪的操作(例如将数字除以字符串),它会提供编译时警告。其次,LISP 是一种非常古老的语言,以至于在创建该语言时,类型理论还没有发展成为一个研究领域。因此,“列表”和“原子”是仅有的两种类型。

这是一个简单的 LISP 程序(使用“Common LISP”方言),它要求用户输入半径,然后给出具有该半径的圆的面积:

(defun AreaOfCircle()
  (terpri)
  (princ "Enter Radius: ")
  (setq radius (read))
  (setq area (* 3.1416 radius radius))
  (princ "Area: ")
  (write area)
)
(AreaOfCircle)
Enter fullscreen mode Exit fullscreen mode

在这里尝试一下!

注意上面程序中的每个语句都是一个列表,包括 I/O 和各种函数的执行。LISP 也具有操作列表的功能:

(append '(1 2 3) '() '(a) '(5 6))
Enter fullscreen mode Exit fullscreen mode

这里,'x是的语法糖(quote x...),它只是返回元素x...而不评估它们(这是默认行为)。

上面的列表通过将其他几个列表按顺序附加到一起来操作它们。上述代码片段的结果是这样的列表:

(1 2 3 a 5 6)
Enter fullscreen mode Exit fullscreen mode

请注意原子a尚未被评估并被数字或字符串替换。

由于 LISP 提供了操作列表的方法,并且每个 LISP 程序本身都由列表组成,因此 LISP 程序在 LISP 语言中定义了数据结构!这意味着(用于操作和运行其他代码的代码)在 LISP 开发人员中很常见。LISP 语法定义了程序的输入、输出以及程序本身的源代码。这个概念被称为同像性 (homoiconicity ),这也是 LISP 对于 ALGOL 类(C 类)语言的用户来说有些陌生的原因之一。

如果您想在 2020 年学习一种很酷的、新的(至少对您来说)语言,我可以建议您学习 LISP 吗?

[返回目录]

#13.功能

Funciton 是一种编程语言,它的名字看起来像有人拼错了“function”,当我读到它时,我总是在心里把它读成“funky town”。

Funciton 是一种类似流程图的二维语言。Funciton 中的阶乘函数可能如下所示:

                   ╓───╖
                   ║ ! ║
                   ╙─┬─╜   ┌───╖  ╔═══╗
               ┌─────┴─────┤ > ╟──╢ 2 ║
               │           ╘═╤═╝  ╚═══╝
 ╔════╗  ┌───╖ │             │
 ║ −1 ╟──┤ + ╟─┴─┐           │
 ╚════╝  ╘═╤═╝   │           │
         ┌─┴─╖   │    ╔═══╗  │
         │ ! ║   │    ║ 1 ║  │
         ╘═╤═╝   │    ╚═╤═╝  │
           │   ┌─┴─╖  ┌─┴─╖  │
           │   │ × ╟──┤ ? ╟──┘
           │   ╘═╤═╝  ╘═╤═╝
           └─────┘      │
Enter fullscreen mode Exit fullscreen mode

Funciton 程序的每个元素都写在一个由 ASCII 行和双线组成的矩形(或“盒子”)内。盒子之间的线承载着程序周围的数据。由于 Funciton 程序具有旋转不变性,因此有五种可能的盒子类型:

  1. 所有边都是双线的:文字值或输入或注释
  2. 三面双线:lambda 表达式
  3. 相邻两侧双线:函数调用
  4. 在相对的两侧双线:函数声明
  5. 单侧双线:调用 lambda 函数
  6. 两侧均无双线:NOT操作员(见下文)

如果一个框没有连接器,那么就无法向其传递数据或从其读取数据,因此该框将成为注释:

  ╔═════════════════════════════════════╗
  ║  Won't you take me to... Funciton?  ║
  ╚═════════════════════════════════════╝
Enter fullscreen mode Exit fullscreen mode

一个带有一行的框要么是文字,要么是请求从 STDIN 输入:

  ╔═════════════════════════════════╗  ╔══════╗
  ║  this is the literal number 42  ║  ║  42  ╟────
  ╚═════════════════════════════════╝  ╚══════╝
  ╔════════════════════════════════╗   ╔══════╗
  ║  this box requests user input  ║   ║      ╟────
  ╚════════════════════════════════╝   ╚══════╝
Enter fullscreen mode Exit fullscreen mode

“旋转不变”意味着上述内容42可以写成


╔══════╗        ╔══════╗  ╔══════╗  ╔═══╧══╗
║  42  ╟───  ───╢  42  ║  ║  42  ║  ║  42  ║
╚══════╝        ╚══════╝  ╚═══╤══╝  ╚══════╝
Enter fullscreen mode Exit fullscreen mode

……并且在每种情况下,它都表示同一个意思(一个字面数字42)。数据从这样的框中“流出”,并流入连接这些框的“线”,而“未完成的部分”表示数据应该写入标准输出 (STDOUT)。因此,上面四个框中的每一个都将42转换为字符的 写入标准*输出 (STDOUT)。(尽管从技术上讲,这必须是四个独立的程序,因为单个 Funciton 程序只能有一个输出。)

当输入以 T 型接头的垂直线形式进入时,线路(或“电线”)在 Funciton 中不是无源的,并且 T 型接头定义分离器……

╔══════╗   │   ╔════════════════════════════════════════════╗
║  42  ╟───┤   ║  Each output line carries the value `42`.  ║
╚══════╝   │   ╚════════════════════════════════════════════╝
Enter fullscreen mode Exit fullscreen mode

...以及NAND门,当输出是垂直线时:

╔══════╗     ╔══════╗  ╔═══════════════════════════════════╗
║  42  ╟──┬──╢  25  ║  ║  Output is (42 NAND 25) or `55`.  ║
╚══════╝  │  ╚══════╝  ╚═══════════════════════════════════╝
Enter fullscreen mode Exit fullscreen mode

仅使用分离器和NAND门,我们就可以定义NOT,,AND,这使我们能够定义任何其他可以想到的函数ORXOR

                                                  ┌──────────────────────┐
╓─────╖        ╓─────╖            ╓────╖          │  ╓─────╖             │
║ not ║     ┌──╢ and ╟──┐      ┌──╢ or ╟──┐       ├──╢ xor ╟─────┐       │
╙──┬──╜     │  ╙─────╜  │     ┌┴┐ ╙────╜ ┌┴┐      │  ╙─────╜ ┌┐  │    ┌┐ │
   │        └─────┬─────┘     └┬┘        └┬┘      └───┬──────┤├──┴──┬─┤├─┘
  ┌┴┐            ┌┴┐           └────┬─────┘           │      └┘     │ └┘
  └┬┘            └┬┘                │                 └────┬────────┘
   │              │                                        │
Enter fullscreen mode Exit fullscreen mode

如果您对 Funcitown 感兴趣,我建议您查看它的 esolangs wiki 页面,或者,只是惊叹于用 Funciton 编写的“99 瓶啤酒”的实现

[返回目录]

#14. ///

相关: 图埃

///(读作“slashes”)是一种所有计算都通过ed风格的字符串替换执行的语言。该语言唯一的“语法”是一个由正斜杠/字符构成的单一结构,用于定义如下形式的字符串替换:

/pattern/replacement/initial
Enter fullscreen mode Exit fullscreen mode

在字符串initial中搜索pattern,将其移除并替换为replacement。然后从新的(修改后的)字符串的开头再次重复此搜索替换过程。如果pattern在字符串中找不到 ,则将initial(或新修改的)字符串打印到控制台,程序终止。

例如:

/NAME/Karl Hungus/Hello, NAME!
Enter fullscreen mode Exit fullscreen mode

上面的 /// 程序将Hello, NAME!在字符串中搜索子字符串NAME,找到后,它将用字符串替换Karl Hungus

/NAME/Karl Hungus/Hello, Karl Hungus!
Enter fullscreen mode Exit fullscreen mode

经过一次迭代后,NAME在修改后的字符串中不再能找到子字符串,因此程序终止,并打印Hello, Karl Hungus!到终端。

/// 中只有一个特殊字符,那就是反斜杠\,它既可以用来转义该/字符,也可以用来转义其本身。任何不包含/\字符的程序都很容易被看作一个 Quine,它会将其源代码打印到控制台上。

/// 中更困难的 quine 是包含\/字符的 quine(极度倾斜的牙签综合症):

/\/\/\/\\\\/\\\\\\\/\\\\\\\/\\\\\\\/\\\\\\\\\\\\\\\\\\\\\\//\/\/\/\\\/\/\\////\\////\\\///\\////\\\///\\////\\\///\\////\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\////\\\///\\////\\\///\\////\\\///\\////\\\///\\\///\\\///\\////\\\///\\////\\\///\\\///\\////\\////\\////\\////\\\///\\////\\\///\\////\\////\\\///\\////\\////\\\///\\////\\\///\\////\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\////\\////\\////\\////\\\///\\////\\////\\\///\\////\\////\\\///\\////\\\///\\////\\\///\\////\\\///\\\///\\\///\\\///\\////\\\///\\\///\\////\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\////\\////\\////\\////\\\///\\////\\////\\\///\\////\\////\\\///\\////\\\///\\////\\\///\\////\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\////\\////\\////\\\///\\////\\\///\\////\\\//\/\/\/\\\/\\\/\\////\//\//\/\/\/\\\\/\\//\\\/\\\/\\\/\\\\\\\/\\\\\\\/\\\/\\\\////\//\//\/\/\/\\\\/\\\/\\\/\\\/\\\\\\\\\\////\/\/\
Enter fullscreen mode Exit fullscreen mode

/// 被Ørjan Johansen间接证明是图灵完备的,他使用该语言为不同的 esolang (按位循环标记)创建了一个解释器,而该解释器本身也是图灵完备的。

[返回目录]

#15.工厂

Factory 是一种非常有趣的语言,你的命令会在“字节工厂”周围移动一个“爪子”。你可以用爪子拾取1s 和0s,将它们移动到存储空间,并创建“一批”位,这些位被分组为 8 位字节,并以 ASCII 字符的形式“传送”到标准输出。Factory 程序文件的.claw扩展名是 ,原因显而易见。

字节工厂最初看起来像这样:

     |
     |
    / \
    \ /



    [1]    | _____________ | _____________ | _____________ |    X    |   [:=:]  | [    ] | !!!!!!!! | &&& 
production |storage space 1|storage space 2|storage space 3| garbage | shipping | supply | Invertor | and
Enter fullscreen mode Exit fullscreen mode

不同的房间有不同的用途:

  • production1在程序开始时创建一个恒定的 s 流,但0如果 a0从爪子中“掉落”到房间中,则可以将其更改为 s 流(掉落 a1会将生产切换回1s 流)
  • 每个sstorage space都包含一叠比特。从爪子上掉落的比特会被添加到这叠比特的顶部,然后爪子可以在任何时候拾起这叠比特,带着这叠比特以及它上面的所有比特。
  • 掉入的比特garbage将被破坏并永远丢失
  • shipping工作原理类似于storage space,直到将位作为 ASCII 字符传递到 STDOUT
  • supply接收用户的输入字符,将其转换为位并以相反的顺序存储为堆栈(因此第一个字符的第一位位于堆栈顶部)
  • 接受invertor一个它反转的位(0变成11变成0
  • 房间and接受两个比特,销毁其中一个。如果其中一个比特是0,则另一个比特会被销毁,因此0只剩下一个

程序员指示爪子在工厂内移动,拾取零件并将它们堆放到各个房间:

  • <告诉爪子向左移动一个房间(如果爪子production已经在房间里,它就不会移动)
  • >告诉爪子向右移动一个房间(如果爪子and已经在房间里,它就不会移动)
  • v告诉爪子把它的所有碎片都扔进这个房间(如果它携带任何碎片),否则捡起这个房间顶部的碎片
  • O运送运输室的物品
  • I要求进入储藏室
  • 等等...

Factory 是一款非常巧妙的作品,一半是游戏,一半是编程语言。我很想看到一个 Factory 调试器,能够真实地展示爪子在工厂里移动,拾取零件并将它们放到不同位置。它可能不是最实用的编程语言,但它绝对是独一无二的。

[返回目录]

#16. 高尔夫语言

在接下来的几篇文章中,我想讨论一些更广泛的语言类别,而不是单一的语言本身。我首先要讨论的是高尔夫语言

高尔夫语言用于代码高尔夫比赛(Code Golf )。这项比赛要求参赛者尝试用尽可能小的源代码(通常以字节为单位)编写程序。代码高尔夫 Stack Exchange (CGSE) 是一个充满活力的编程语言爱好者社区,他们使用主流和深奥的编程语言。APL代码高尔夫比赛的常用语言,尽管许多语言是专门为高尔夫比赛创建的,包括:

……还有更多。我把 J 和 Jelly 归为一类,是因为 Jelly 的开发者说他们主要受到 J 编程语言的影响,而 J 的设计者是…… APL 的创始人Kenneth E. Iverson 。你可以在 CGSE 的“语言展示”主题中找到这些以及更多高尔夫语言

为了让你体会一下“代码高尔夫”的乐趣,我给你一个挑战:编写一个程序来检测回文字符串。回文字符串是指正读和反读都一样的字符串。程序如何实现并不重要,重要的是它需要以某种方式指示传递给它的输入是否是回文。作为参考,一个用 Java 编写的极简回文检测程序可能如下所示:

import java.util.*; 

public class P {
  public static void main (String a[]) {

    String o, r = "";
    Scanner s = new Scanner(System.in);

    o = s.nextLine();  

    for (int i = o.length() - 1; i >= 0; i--)
      r = r + o.charAt(i);

    System.out.println(o.equals(r));
  }
}
Enter fullscreen mode Exit fullscreen mode

为了清楚起见,我留下了空格,但在真正的代码高尔夫比赛中,我们会将其压缩为:

import java.util.*;public class P {public static void main(String a[]){String o,r="";Scanner s=new Scanner(System.in);o=s.nextLine();for(int i=o.length()-1;i>=0;i--)r=r+o.charAt(i);System.out.println(o.equals(r));}}
Enter fullscreen mode Exit fullscreen mode

……然后计算一下解法中的字节数。由于这些都是 ASCII 字符,所以字节数就是字符数,而我的 Java 解法有 216 个字节。看看这些高尔夫语言怎么样?

这是Brachylog中的解决方案(3 个字节):

I↔I
Enter fullscreen mode Exit fullscreen mode

...这是Jelly中的一个(5 个字节):

ḂŒ
ŒḂ
Enter fullscreen mode Exit fullscreen mode

...和 ​​05AB1E (3 个字节):

ÂQÂ
Enter fullscreen mode Exit fullscreen mode

...J(15字节):

-:|.NB. .BN.|:-
Enter fullscreen mode Exit fullscreen mode

...GolfScript(11字节):

.-1%=#=%1-.
Enter fullscreen mode Exit fullscreen mode

...和 ​​Dyalog APL(6 字节):

⌽≡⊢⊢≡⌽
Enter fullscreen mode Exit fullscreen mode

相比之下,我的解决方案突然显得不那么令人印象深刻了。你可以看到,大多数这类“代码高尔夫”语言在其源代码中大量使用 UNICODE 字符:一个字符就能编码出一个极其复杂的操作,因此使用“代码高尔夫”语言通常意味着只需记住大量单个字符的功能即可。如果你对“代码高尔夫”感兴趣,我建议你查看“代码高尔夫 Stack Exchange”,或者参加当地的线下“代码高尔夫”比赛(通常,这些比赛仅限于一种语言或一组预定义的语言)。

[返回目录]

#17. 具有二维源代码的语言

由于大多数自然书写语言只能沿一个方向阅读(英语中是从左到右),并且会“环绕”页面边缘,因此编程语言也应该沿此方向阅读,这很符合直觉。但一些语言设计者决定“更好地”利用这些语言书写和显示的二维空间,允许源代码从左到右、从上到下或沿对角线方向阅读。这种更加多样化的阅读方向催生了以下一些创作:

...等等。这些语言通常包含一些可以改变代码读取方向的结构,就像Piet的黑色像素“墙”一样。

Re:direction仅使用 UNICODE 箭头 (◄、▲、►、▼) 来引导程序流并将这些方向添加到队列中,另外还使用一条从队列中弹出方向的指令 (♦),从而实现循环和控制流。程序的输出只能是整数,但这些整数可以被解释为 ASCII 字符。例如,这是一个用 Re:direction 编写的“Hello, World!”程序,您可以点击此处试用

HexagonyBeeswax中,代码写在等宽字符组成的六边形网格上。Hexagony 中的“Hello, World!”程序可能如下所示:

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

...在 Beeswax 中打印第 - 个斐波那契数的程序N可能如下所示:

           ;{#'<>~P~L#MM@>+@'p@{;
 _`n`TN`F(`{`)=`X~P~K#{; d~@M<
Enter fullscreen mode Exit fullscreen mode

Beeswax 允许程序员召唤“蜜蜂”,从而增加了复杂性,蜜蜂充当指针,在程序中向各个方向移动并彼此独立地完成任务。

Maze中,程序的源代码看起来像......一个迷宫:

               ##,##,##    // fibonacci
            ##,##,^^,##,##
            ##,..,<>,PP,##
            ##,..,##,..,##,##,##,##,##,##,##,##  // left column is fib(n), right column is fib(n+1).
##,##,##,##,##,%D,..,LD,..,**,..,..,..,..,..,##  // the small left loop sets fib(n) to 0; simultaneously,
##,..,..,..,##,>>,##,..,## ##,##,##,##,##,..,##  // the small right loop sets a clone of fib(n+1) to fib(n+1)+f(n).
##,MM,##,..,##,..,##,..,##,##,..,..,..,##,..,##  // (this technique is similar to brainfuck [->+<])
##,..,**,FL,..,02,##,%R,..,##,..,##,PP,##,..,##  // the small loop at the bottom does nothing, but make sure
##,##,##,NL,##,##,##,%D,<>,01,FR,..,..,##,..,##  // that the original fib(n+1) is synchronized with the other cars.
      ##,>>,##,##,##,..,##,##,03,##,##,##,..,##  // then fib(n+1) goes to left column and fib(n+1)+fib(n) to right column
      ##,(),##,..,..,FM,..,..,%R,..,..,..,..,##
      ##,##,##,..,##,..,##,##,##,##,##,##,##,##
            ##,..,..,..,##
            ##,##,##,##,##
PP-> +=1
MM-> -=1
FR-> IF ** THEN %U ELSE %D
FL-> IF ==0 THEN %D ELSE %L
FM-> IF ** THEN %L ELSE %R
LD-> IF ** THEN %L ELSE %D
NL-> ="\n"
Enter fullscreen mode Exit fullscreen mode

在该语言中,“汽车”从起始位置 生成^^,每个“地图”只能有一辆汽车。逗号,用于分隔程序的“单元”,每个单元都是一个双字符序列。汽车无法穿过墙壁##,而是沿着路径行驶..,并由函数对其执行操作,这些函数由两个大写字母组成,在源代码中定义,但在迷宫之外,如上所示(PPMM等)。

Oliver Faircliff甚至用 C++ 设计了这个漂亮的动画迷宫解释器,它看起来更像是一款低成本智能手机游戏,而不是一种编程语言。

市面上有种类繁多的二维(以及更高维)编程语言,其中许多比指示程序流程的箭头要复杂得多。例如,(尚未实现的)无限维 Tengwar Meltdown (IDTM)语言是一种用《指环王》中的Tengwar脚本编写的深奥语言。它是一种无限维、基于指针的语言,其中数据存储在一个无限大小的数组中,并且代码会随着时间的推移通过熵衰减(另见:)。因此,多次运行的循环会在程序运行过程中退化并改变其含义。

正当你认为深奥的语言不可能变得更奇怪时。

[返回目录]

#18. 强调源代码美学的语言

当你思考源代码的美观性时,你可能会想到空格。程序的视觉结构主要由代码块、空行、缩进等元素定义。你可能不会考虑源代码中的字符会如何影响其美观性。例如,带有大量曲线的字符可以呈现出“波浪形”、“气泡状”或“平滑”的外观:

s@Ss@S$3CO0oc896$3Cs@S$3CO0oc896O0os@S$3CO0oc896c896
Enter fullscreen mode Exit fullscreen mode

...而具有大量直线的字符可以传达“锯齿状”,“锐利”或“混乱”:

/\|EL/H>+-_=IT\MN|F#^<ZK/k\vx|/>+V|Xzw/WF#^<ZK/k\vx|/>+-_=\
Enter fullscreen mode Exit fullscreen mode

一些语言设计者确实考虑过某些字符的美学特性,并利用它们来实现其语言的特定目标。例如,Grassw的创建者想要设计一种源代码看起来像一片凌乱的草坪的语言。所有 Grass 源代码都只使用字符、W编写v

    _, ._
  ( ・ω・) んも〜
  ○={=}〇,
   |:::::::::\, ', ´
、、、、し 、、、(((.@)wvwwWWwvwwWwwvwwwwWWWwwWw
wWWWWWWwwwwWwwvwWWwWwwvwWWW

作ってみたwwwww
とりあえず公開wwwwwwwっうぇ
Enter fullscreen mode Exit fullscreen mode

其他语言设计者要求他们的源代码类似于某种ASCII 艺术,例如DNA#(C# 的一种玩法),它的源代码看起来像 DNA 双螺旋:

    AT
   T--A
  A----T
  T-----A
  T-----A
  G----C
   T--A
    GC
    CG
   C--G
  A----T
  A-----T
  T-----A
  A----T
   A--T
    GC
    AT
   C--G
  T----A
  C-----G
  T-----A
  G----C
   C--G
    CG
...
Enter fullscreen mode Exit fullscreen mode

如果您对这些类型的语言感兴趣, esolangs.org上有很多尚未实现的编程语言的描述,包括:

... Cactusi,其源代码应该看起来像沙漠中的仙人掌(或Google Chrome 恐龙游戏

     ||    ||  
   ==||   =||=
_____||____||____
Enter fullscreen mode Exit fullscreen mode

...,其外观看起来像一棵树(或某种灌木):

      ^
    ^^|^^
   ^^\|/^^
   H^ |/^^^
     \| e
      |/
   ol~|
     \|
  , 32|
   \/ |
    \ |  W
 l   \| /
 \  d |/  o
  \/ !|r /  
   \/ |\/
    \ |/
     \|
Enter fullscreen mode Exit fullscreen mode

...或Rotary,这是 BF 衍生品,其源代码必须以圆圈形式书写:

     !!!,.v
  !!!      !!!
 !            !
!              !
!              !
!              !
 !            !
  !!!      !!!
     !!!!!!

     !!!,.^
  !!!      !!!
 !            !
!              !
!              !
!              !
 !            !
  !!!      !!!
     !!!!!!
Enter fullscreen mode Exit fullscreen mode

“源代码即艺术”无疑是一个活跃且良好的概念,至少在 esolang 社区中是如此。

[返回目录]

#19. 语言的源代码看起来像___

与#18中的语言略有不同的是以下语言,它们使用简化的字符集编写,或者添加大量额外的“装饰”以使语言看起来像……

一份食谱

Chef编程语言(不要与Chef 配置管理工具混淆)是一种设计得像菜谱一样的语言。以下是 Chef 编写的“Hello, World!”程序:

Hello World Souffle.

This recipe prints the immortal words "Hello world!", in a basically brute force way. It also makes a lot of food for one person.

Ingredients.
72 g haricot beans
101 eggs
108 g lard
111 cups oil
32 zucchinis
119 ml water
114 g red salmon
100 g dijon mustard
33 potatoes

Method.
Put potatoes into the mixing bowl. Put dijon mustard into the mixing bowl. Put lard into the mixing bowl. Put red salmon into the mixing bowl. Put oil into the mixing bowl. Put water into the mixing bowl. Put zucchinis into the mixing bowl. Put oil into the mixing bowl. Put lard into the mixing bowl. Put lard into the mixing bowl. Put eggs into the mixing bowl. Put haricot beans into the mixing bowl. Liquefy contents of the mixing bowl. Pour contents of the mixing bowl into the baking dish.

Serves 1.
Enter fullscreen mode Exit fullscreen mode

Chef 的设计原则之一是“程序食谱不仅应该生成有效的输出,还应该易于准备并且美味可口。”我认为,上述蛋奶酥食谱是否“美味”尚待考证,但还有一个不同的“Hello, World!”食谱,可以制作出令人惊喜的美味巧克力蛋糕。

点字

路易斯·布莱叶 (Louis Braille)是为视障人士发明触觉书写系统的创始人,该系统现在通常被称为盲文(全部小写),但他的姓氏也赋予了编程语言盲文 (Braille )(大写)。

盲文(编程语言)仅使用 UNICODE 盲文代码(U+2800 至 U+28FF)编写。由于盲文代码共有 256 个(写在 2x8 的网格上),盲文的创始人 Brian McPherson 决定将它们排列在一个 16x16 的网格中,这样可以执行 16 个操作,并为每个操作传递一个十六进制数字。

下面是一个用 ASCII 字符打印“Hello, World!”的盲文程序:

 ⠆⠄⡒⡆⡘⠀⢐⠊⠦⢦⠗⢾⠿⠂⢢⢾⢦⢦⠮⢄
Enter fullscreen mode Exit fullscreen mode

还有一个“Hello, World!”,以盲文形式打印其输出:

 ⠆⡆⢤⡔⠈⠖⠙⠇⠗⠕⠺⠀⠂⠕⠇⠇⠑⠓
Enter fullscreen mode Exit fullscreen mode

一出戏

(臭名昭著的)莎士比亚语言在源代码中添加了许多额外的修饰,使其与同名戏剧中的某部作品十分相似。该语言的创建者对此进行了如下总结:

“剧中的角色都是变量。如果你想赋予一个角色,比如哈姆雷特,一个负值,你就把他和另一个角色放在舞台上,让那个角色侮辱哈姆雷特。

输入和输出是通过让角色倾听自己的内心或说出自己的想法来完成的。该语言包含条件句(角色之间互相提问)和跳跃句(角色决定进入特定的动作或场景)。角色也是可以压栈和弹出的栈。

莎士比亚写的“Hello, World!”有点太长了,无法在这里重现,但这里有一个程序,它接受任何输入,将其反转,并打印反转的字符串:

Outputting Input Reversedly.

Othello, a stacky man.
Lady Macbeth, who pushes him around till he pops.


                    Act I: The one and only.

                    Scene I: In the beginning, there was nothing.

[Enter Othello and Lady Macbeth]

Othello:
 You are nothing!

                    Scene II: Pushing to the very end.

Lady Macbeth:
 Open your mind! Remember yourself.

Othello:
 You are as hard as the sum of yourself and a stone wall. Am I as
 horrid as a flirt-gill?

Lady Macbeth:
 If not, let us return to scene II. Recall your imminent death!

Othello:
 You are as small as the difference between yourself and a hair!

                    Scene III: Once you pop, you can't stop!

Lady Macbeth:
 Recall your unhappy childhood. Speak your mind!

Othello:
 You are as vile as the sum of yourself and a toad! Are you better
 than nothing?

Lady Macbeth:
 If so, let us return to scene III.

                    Scene IV: The end.

[Exeunt]
Enter fullscreen mode Exit fullscreen mode

摇滚歌词

Rockstar语言的设计使其源代码看起来像一首俗气的 80 年代摇滚民谣的歌词。它由 Dylan Beattie 于 2018 年创建,灵感来自一条推文,该推文建议有人应该开发一种名为 Rockstar 的语言,以迷惑那些总是为客户寻找“摇滚明星开发者”的招聘人员。

这是 Rockstar 中的 FizzBu​​zz:

 Midnight takes your heart and your soul
 While your heart is as high as your soul
 Put your heart without your soul into your heart

 Give back your heart


 Desire is a lovestruck ladykiller
 My world is nothing 
 Fire is ice
 Hate is water
 Until my world is Desire,
 Build my world up
 If Midnight taking my world, Fire is nothing and Midnight taking my world, Hate is nothing
 Shout "FizzBuzz!"
 Take it to the top

 If Midnight taking my world, Fire is nothing
 Shout "Fizz!"
 Take it to the top

 If Midnight taking my world, Hate is nothing
 Say "Buzz!"
 Take it to the top

 Whisper my world
Enter fullscreen mode Exit fullscreen mode

恋物情色

最后但并非最不重要的是Fetlang,一种非常适合工作场所的语言,其源代码类似于恋物癖色情内容,并且“根据 BSDM(BSD,修改版)许可证获得许可”。

这是一个相对温和的 Fetlang 程序,它只是回应传递给它的参数:

Make Sean moan
Worship Carrie's feet

Bind Amy to Saint Andrew's Cross
    Have Amy hogtie Sean
    If Amy is Carrie's bitch
        Make Slave scream Sean's name
        Make Sean moan
Enter fullscreen mode Exit fullscreen mode

从那时起,事情只会变得更加危险。

[返回目录]

#20. 问#

IBM 在2017 年的一篇博客文章中断言“未来属于量子”,并顺便宣传了他们自己的量子计算机 IBM Q。量子计算的理论基础是由保罗·贝尼奥夫、理查德·费曼和其他许多人在 20 世纪 80 年代初奠定的,但直到最近,工程技术才赶上理论,建造像 IBM Q 这样的量子计算机才成为可能。

量子计算在某些领域(例如密码学、物理模拟以及求解方程组等高度并行化的问题)比传统(经典)计算具有巨大的优势。最近,谷歌宣布其“量子霸权”:其一项算法在其 54 量子比特 Sycamore 量子处理器上仅需 200 秒即可运行。而同等算法在最先进的经典超级计算机上则需要 10,000 年的处理时间,这几乎是不可能的。

量子计算机编程与传统计算机编程完全不同,因为其中涉及到量子纠缠、相干性和不确定性等量子效应。即使在最基础的层面上,量子编程也与传统编程截然不同。传统的逻辑“与”、“或”和“非”门被阿达玛门托弗利门泡利 X、Y、Z 门所取代。学习量子计算并非仅仅学习一门新的编程语言,而是学习一门全新的、极其困难的技能(背后蕴含着大量的数学和物理知识)。

尽管如此,微软仍试图通过其Q# 编程语言尽可能顺利地实现从传统编程到量子编程的过渡。Q# 于 2017 年底首次向公众发布。Q# 加入了微软“sharp”编程语言家族,之前是 C# 和 F#。微软的 Visual Studio 和VS Code IDE提供了 Q# 扩展,这些扩展与量子模拟器打包在一起(因为大多数人还没有机会接触到真正的量子计算机)。

Q# 代码看起来与 C# 代码非常相似,微软也提供了大量实用的文档和示例供您参考。由于 Q# 旨在在实际的量子计算机上运行,​​因此它通常需要在其他语言(例如 Python 或 C#)中运行,并且该语言的量子模拟器可以与 Q# 进行交互。

例如,以下是一段 Q# 代码,当在 C# 宿主代码中调用时,它将测量一对纠缠量子比特中一个的值,然后测量第二个的值。由于纠缠态的存在,返回的值始终相同:

operation TestBellState(count : Int, initial : Result) : (Int, Int, Int) {
  mutable numOnes = 0;
  mutable agree = 0;

  using ((q0, q1) = (Qubit(), Qubit())) {
    for (test in 1..count) {
      Set(initial, q0);
      Set(Zero, q1);

      H(q0);
      CNOT(q0, q1);
      let res = M(q0);

      if (M(q1) == res) {
        set agree += 1;
      }

      // Count the number of ones we saw:
      if (res == One) {
        set numOnes += 1;
      }
    }

    Set(Zero, q0);
    Set(Zero, q1);
  }

  // Return number of times we saw a |0> and number of times we saw a |1>
  return (count-numOnes, numOnes, agree);
}
Enter fullscreen mode Exit fullscreen mode

[返回目录]


编程语言,如同现实世界中的语言一样,形态各异,千差万别。并非每种语言都必须是声明式的、函数式的或面向对象的。一种语言甚至不需要能够定义命名变量或函数,就能计算你交给它的任何数据。正如上面的列表所证明的那样,编程语言拥有无限的可能性。

如果你和我一样对编程语言着迷,我推荐你访问esolangs.org,在那里你可以了解更多关于这些语言以及其他许多深奥语言的知识。如果你有兴趣创建自己的编程语言,请关注这里。我希望在接下来的几个月里推出一本关于从零开始开发你自己的语言和编译器的指南!


如果您喜欢以上内容,请在Dev.ToTwitter上关注我,获取更多精彩内容。如果您真的喜欢,或许可以通过Ko-Fi捐赠一些您国家/地区的货币单位来支持我

无论您做什么,感谢您的阅读!

文章来源:https://dev.to/awwsmm/20-intriguing-unusual-and-goofy-programming-languages-238f
PREV
对抗冒名顶替综合症的20种方法
NEXT
AWS 认证 - 学习指南(第 1 部分)