介绍
Red 使用数据堆栈来传递参数并返回结果。堆栈上的每个值都是一个装箱结构,大小为 4 个平台指针,并且可能包含对外部缓冲区的引用;这意味着您需要构建它们并将它们推送到堆栈上,尽管如果您返回它们,一些原始的 Red/System 类型(如 eglogic!
或integer!
)会自动提升。
但是,在您的情况下,不需要使用堆栈,因为您想直接在块中分配值。具有低级编程经验和使用 Red运行时 API的Red/System知识是完成此任务的基本先决条件。因此,让我们以您的示例并逐步进行操作。
开箱
- 你有一个块,你想向它附加两个值,
123
并且"Hello"
. 假设您想从 Red/System 执行此操作。为此,我们需要编写一个例程。
list: []
foo: routine [][...]
在此例程中,您需要获取list
word 引用的块。很难做到这一点的方法是实例化一个符号并通过其 ID 在全局上下文中查找值:
list: []
foo: routine [
/local
blk [red-block!]
][
blk: as red-block! _context/get-global symbol/make "list"
]
作为一个论点传递list
会更合理,但出于教育目的,我会保持原样。
现在我们要追加123
到这个块。有一个block/rs-append
函数可以做到这一点,但它接受一个装箱的参数。所以我们需要123
先把自己装箱。
- 这就是装箱整数的样子;如您所见,它只是 32 位
123
值 + 插槽标头和填充。我们可以自己构造和初始化这样的结构:
int: stack/push* ; allocate slot on data stack
int/header: TYPE_INTEGER ; set datatype
int/value: 123 ; set value
幸运的是,Red 运行时已经使用带有 Red/System并返回盒装结构
integer/box
的函数来
覆盖它:integer!
red-integer!
integer/box 123
- 现在我们需要将这个装箱的整数附加到一个块中。直观地说,我们可以检查
block.reds
定义并找到block/rs-append
符合我们要求的定义:
block/rs-append blk as red-value! integer/box 123
在这一步结束时,我们有:
list: []
foo: routine [
/local
blk [red-block!]
][
blk: as red-block! _context/get-global symbol/make "list"
block/rs-append blk as red-value! integer/box 123
]
现在我们要追加一个"Hello"
字符串,但首先我们需要构造它。红色字符串支持 UTF-8 并使用固定大小的内部编码(每个字符 1、2 或 4 个字节,取决于最大代码点大小);手动获取很多细节,因此构造此类字符串的典型方法是将其从c-string!
.
list: []
foo: routine [
/local
blk [red-block!]
str [c-string!]
][
blk: as red-block! _context/get-global symbol/make "list"
block/rs-append blk as red-value! integer/box 123
str: "Hello"
]
检查string!
数据类型运行时定义load
,您会注意到一些以;为前缀的方便包装器。这是一个约定,表明此类函数可用于从低级 Red/System 部分构造(即“加载”)高级 Red 值,在我们的例子red-string!
中来自c-string!
. 由于我们想在块的尾部构造它,我们可以使用string/load-in
:
str: "Hello"
string/load-in str length? str blk UTF-8
请注意,我使用length?
而不是size?
排除 NUL 终止的字节。
结论
就是这个。归根结底,我们可以稍微整理一下代码并检查它是否可以正常工作:
Red [Note: "compile in release mode (-r flag)"]
list: []
foo: routine [
/local
blk [red-block!]
int [integer!]
str [c-string!]
][
blk: as red-block! _context/get-global symbol/make "list"
int: 123
str: "Hello"
block/rs-append blk as red-value! integer/box int
string/load-in str length? str blk UTF-8
]
foo
probe list
在发布模式下编译此脚本并从 shell 执行生成的二进制文件会给我们预期的结果:
[123 "Hello"]
毋庸置疑,这一切对于新手来说可能看起来相当难以承受:虽然 Red 和 Red/System 都有不错的文档和学习资源,但它们通过运行时交互的桥梁是未知的领域。这样做的原因是因为项目正在发展,API 还没有稳定下来,所以,目前还不是记录它并确定设计决策的合适时间。有经验的开发人员可以很快掌握方向,但这需要对 Red 的评估模型有扎实的概念理解——这些基础知识是您首先需要掌握的。
您还可以学习大量的库绑定——从原始示例来看,您正在尝试在 SQLite 之上创建一个 CRUD 视图界面。