有趣的编程语言 Red

Red 项目最早始于 2011 年,项目由 Nenad Rakocevic 主导。Red 语言是一种同时具有函数式、声明式、符号式特性的现代编程语言,其目标是构建成一个全栈编程语言。Red 语言受到 Rebol 语言启发,两者语法高度相似。和 Rebol 语言只能解释执行不同,Red 语言还提供了 AOT 编译(生成独立的可执行文件)功能,在未来还将支持 JIT 编译。

Red 语言的主要特性:

最神奇之处在于,这样一个全能的语言,它的编译器大小仅 1MB 多

安装

在 Windows 上可以使用 Scoop 安装 Red 编译器:

powershellscoop install red-toolchain	
scoop install red       # 命令行控制台/解释器(可选)
scoop install red-view  # GUI 控制台/解释器(可选)

以下是一个 Red 语言的 Hello World 示例:

redRed [title: "Hello World"]
 
print "Hello World!"
hello.red

交叉编译

Red 语言工具链只需要简单的参数设置便可以实现交叉编译。目前支持的编译目标平台有:

MSDOS        : Windows, x86, console (+ GUI) applications
Windows      : Windows, x86, GUI applications
WindowsXP    : Windows, x86, GUI applications, no touch API
Linux        : GNU/Linux, x86, console (+ GUI) applications
Linux-GTK    : GNU/Linux, x86, GUI only applications
Linux-musl   : GNU/Linux, x86, musl libc
Linux-ARM    : GNU/Linux, ARMv5, armel (soft-float)
RPi          : GNU/Linux, ARMv7, armhf (hard-float)
RPi-GTK      : GNU/Linux, ARMv7, armhf (hard-float), GUI only applications
Pico         : GNU/Linux, ARMv7, armhf (hard-float), uClibc
Darwin       : macOS Intel, console or GUI applications
macOS        : macOS Intel, GUI-only, applications bundles
Syllable     : Syllable OS, x86
FreeBSD      : FreeBSD, x86
NetBSD       : NetBSD, x86
Android      : Android, ARMv5
Android-x86  : Android, x86

使用以下命令可以在 Windows 上分别交叉编译 Windows、Linux 和 macOS 的可执行文件:

powershellred-toolchain -t MSDOS hello.red    # MSDOS 指 Windows 控制台程序
red-toolchain -t Linux hello.red
red-toolchain -t Darwin hello.red

目前,Red 只能编译生成 32 位程序,计划未来支持 64 位。

GUI 示例

Red 还自带一套简易的 GUI 组件,这使其拥有了跨平台 GUI 开发能力。

redRed [title: "GUI Example" needs: 'view]
 
view [
    title "GUI Example"
    below
    input: field 400x30 "Input some text here"
    across
    button "Show" [
        message: input/text
        alert message
    ]
    button "Exit" [unview]
]

Red 为 GUI 引擎设计了一套 DSL 方言和一个响应式框架。该 GUI 底层在 Windows 下使用原生 API,在 Linux 下使用 Gtk3,在 macOS 下使用 Cocoa。不过 UI 组件数量很少,没多少实用价值。

嵌入 Red/System

Red/System 是 Red 的底层开发方言,使用静态类型和手动内存管理,类似于 C 语言。可以在普通 Red 代码中嵌入 Red/System 代码进行混合编程。此外,Red 源代码也是通过转译成 Red/System 后进行编译的。

下面代码展示了在 Red 中调用本地 Windows API MessageBox() 弹出消息框:

redRed [title: "MessageBox Hello World"]
 
#system [
    #import [ "user32.dll" stdcall [
        message-box: "MessageBoxA" [
            hWnd     [integer!]
            pText    [c-string!]
            pTitle   [c-string!]
            uFlag    [integer!]
            return:  [integer!]
        ]
    ]]
]
 
show-msg: routine [
    text   [string!]
    title  [string!]
    /local
        c-text [c-string!]
        c-title [c-string!]
][
    c-text: as c-string! string/rs-head text
    c-title: as c-string! string/rs-head title
    message-box 0 c-text c-title 0
]
 
show-msg "World" "Hello"
吐槽一下

Red 的文档几乎没有,示例代码十分有限,社区也几乎不存在。相关资源有限,因此别指望 AI 能写出正确的 Red 代码。上述代码是我根据 Red 编译器源代码写出来的,而 AI 写的代码没有一例可以通过编译。

Homoiconicity

Homoiconicity 一般翻译成同像性,也就是通常所说的代码即数据 (code as data)。简单地说,就是该语言的代码可以像数据一样进行操作,从而实现元编程。

Red 语言通过 Block 实现同像性。比如代码 block-example: [1 2 foo "foo" "bar" bar],其中方括号包起的部分就表示一个 Block,并将其赋值给 block-example 变量。Block 即可以用来表示列表,又可以用来表示字典,还可以用来表示代码。不同于 Lisp 系语言,Red 不需要显式声明 Block 的类型,编译器会根据上下文自动识别。

redblock-example: [3 2 1 foo "bar" name "Tony"]
 
; 将 block 当作列表访问
probe block-example/1    ; 3
probe block-example/5    ; "bar"
 
; 将 block 当作字典访问
probe block-example/foo  ; "bar"
probe block-example/name ; "Tony"
 
; 删除 block 中倒数第二个元素 name
remove at block-example (length? block-example) - 1
probe block-example      ; [3 2 1 foo "bar" "Tony"]
 
; 将 block 当作代码运行,block 的最后一个元素会作为返回值
foo: func [arg] [print ["The arg is:" arg]]
result: do block-example ; The arg is: bar
probe result             ; "Tony"

其中,内置函数 probe 用于打印变量内容;内置函数 do 用于运行 Block 代码;斜杠 / 表示路径分隔,类似其他语言里的 .->

总结

Red 语言太小众了,社区孱弱,文档缺失。它目前远远未达到可用阶段,1.0 版本还遥遥无期。另外缺点也不少,比如错误信息可读性差,也缺乏调试工具。只能算是一个有趣的玩具吧。

Red 语言让人别扭的一点是,由于 Red 的标识符允许包含特殊字符 (+ - : ? & * _ ! ' < > | ~ 等),因此标识符和运算符之间必须用空格分隔。比如 a-ba - b 完全是两个意思:

reda: 2
b: 1
a-b: 999

probe a-b    ; 999
probe a - b  ; 1

另外 Red 也没有运算符优先级的概念。比如 x: 1 + 2 / 3 * 4 的值是 4,等价于 x: ((1 + 2) / 3) * 4