如何将值从 Red/System 传递给 Red?
How to pass value from Red/System to Red?
我需要将我在 Red/System 中生成的值传递给 Red。我发现了文档,但没有找到如何使用它的示例。这是我的代码:
Red []
#system [
data!: alias struct! [
a [integer!]
b [c-string!]
]
data: declare data!
_foo: func [return: [data!]]
[
data/a: 123
data/b: "Hello"
return data
]
]
sqlite: context
[
my-red-block: []; I want to place here: 123 "Hello"
foo: routine [
/local
x [data!]
]
[
x: _foo
; next line do now work
; push my-red-block x/a
]
]
view [button "Select" [sqlite/foo]]
my-red-block
这里是红色 block
,我想用 Red/System 部分的数据填充。
https://github.com/meijeru/red.specs-public/blob/master/specs.adoc#routine-type
简介
Red 使用数据栈传递参数,return 传递结果。堆栈上的每个值都是一个盒装结构,大小为 4 个平台指针,并且可能包含对外部缓冲区的引用;这意味着您需要构造它们并将它们压入堆栈,尽管如果您 return 某些原始 Red/System 类型(例如 logic!
或 integer!
)会自动提升.
但是,在您的情况下,不需要使用堆栈,因为您希望直接在块中分配值。 low-level 编程经验和 Red/System with Red runtime API 知识是完成此任务的必要先决条件。因此,让我们以您的示例为例,逐步完成。
开箱
- 您有一个块,您想要向其附加两个值,
123
和 "Hello"
。假设您想从 Red/System 开始。为此,我们需要编写一个例程。
list: []
foo: routine [][...]
在这个例程中,您需要获取list
字引用的块。困难的方法是实例化一个符号并通过其 ID 在全局上下文中查找值:
list: []
foo: routine [
/local
blk [red-block!]
][
blk: as red-block! _context/get-global symbol/make "list"
]
将 list
作为参数传递会更合理,但出于教育目的我会保留它 as-is。
现在我们要将 123
附加到此块。 block/rs-append
函数正是这样做的,但它接受一个盒装参数。所以我们需要先给自己装箱123
- This 是装箱整数的样子;如您所见,它只是 32 位
123
值 + 插槽 header 和填充。我们可以自己构造和初始化这样的结构:
int: stack/push* ; allocate slot on data stack
int/header: TYPE_INTEGER ; set datatype
int/value: 123 ; set value
幸运的是,Red 运行时已经用 integer/box
函数覆盖了它,该函数采用 Red/System integer!
和 returns 盒装 red-integer!
结构:
integer/box 123
- 现在我们需要将这个装箱的整数附加到一个块中。直觉上,我们可以检查
block.reds
definitions 并找到符合我们要求的 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 并使用 fixed-size 内部编码(每个字符 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!
datatype runtime definitions 你会发现一些方便的包装器以 load
为前缀;这是一个约定,表明此类函数可用于构造(即 "load")high-level 来自 low-level Red/System 部分的红色值,在我们的例子中来自 red-string!
c-string!
。由于我们想在块的尾部构造它,我们可以使用 string/load-in
:
str: "Hello"
string/load-in str length? str blk UTF-8
请注意,我使用 length?
而不是 size?
来排除 NUL-terminated 字节。
结论
就是这样。在一天结束时,我们可以稍微整理一下代码并检查它是否有效:
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 的评估模型有扎实的概念理解——这些基础知识是您首先需要掌握的。
还有大量的 library bindings 可供您学习——从原始示例来看,您正试图在 SQLite 之上创建一个 CRUD 视图界面。
我需要将我在 Red/System 中生成的值传递给 Red。我发现了文档,但没有找到如何使用它的示例。这是我的代码:
Red []
#system [
data!: alias struct! [
a [integer!]
b [c-string!]
]
data: declare data!
_foo: func [return: [data!]]
[
data/a: 123
data/b: "Hello"
return data
]
]
sqlite: context
[
my-red-block: []; I want to place here: 123 "Hello"
foo: routine [
/local
x [data!]
]
[
x: _foo
; next line do now work
; push my-red-block x/a
]
]
view [button "Select" [sqlite/foo]]
my-red-block
这里是红色 block
,我想用 Red/System 部分的数据填充。
https://github.com/meijeru/red.specs-public/blob/master/specs.adoc#routine-type
简介
Red 使用数据栈传递参数,return 传递结果。堆栈上的每个值都是一个盒装结构,大小为 4 个平台指针,并且可能包含对外部缓冲区的引用;这意味着您需要构造它们并将它们压入堆栈,尽管如果您 return 某些原始 Red/System 类型(例如 logic!
或 integer!
)会自动提升.
但是,在您的情况下,不需要使用堆栈,因为您希望直接在块中分配值。 low-level 编程经验和 Red/System with Red runtime API 知识是完成此任务的必要先决条件。因此,让我们以您的示例为例,逐步完成。
开箱
- 您有一个块,您想要向其附加两个值,
123
和"Hello"
。假设您想从 Red/System 开始。为此,我们需要编写一个例程。list: [] foo: routine [][...]
在这个例程中,您需要获取
list
字引用的块。困难的方法是实例化一个符号并通过其 ID 在全局上下文中查找值:list: [] foo: routine [ /local blk [red-block!] ][ blk: as red-block! _context/get-global symbol/make "list" ]
将
list
作为参数传递会更合理,但出于教育目的我会保留它 as-is。现在我们要将
123
附加到此块。block/rs-append
函数正是这样做的,但它接受一个盒装参数。所以我们需要先给自己装箱123
- This 是装箱整数的样子;如您所见,它只是 32 位
123
值 + 插槽 header 和填充。我们可以自己构造和初始化这样的结构:
幸运的是,Red 运行时已经用int: stack/push* ; allocate slot on data stack int/header: TYPE_INTEGER ; set datatype int/value: 123 ; set value
integer/box
函数覆盖了它,该函数采用 Red/Systeminteger!
和 returns 盒装red-integer!
结构:integer/box 123
- 现在我们需要将这个装箱的整数附加到一个块中。直觉上,我们可以检查
block.reds
definitions 并找到符合我们要求的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 ]
- This 是装箱整数的样子;如您所见,它只是 32 位
现在我们要追加一个
"Hello"
字符串,但首先我们需要构造它。红色字符串支持 UTF-8 并使用 fixed-size 内部编码(每个字符 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!
datatype runtime definitions 你会发现一些方便的包装器以load
为前缀;这是一个约定,表明此类函数可用于构造(即 "load")high-level 来自 low-level Red/System 部分的红色值,在我们的例子中来自red-string!
c-string!
。由于我们想在块的尾部构造它,我们可以使用string/load-in
:str: "Hello" string/load-in str length? str blk UTF-8
请注意,我使用
length?
而不是size?
来排除 NUL-terminated 字节。
结论
就是这样。在一天结束时,我们可以稍微整理一下代码并检查它是否有效:
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 的评估模型有扎实的概念理解——这些基础知识是您首先需要掌握的。
还有大量的 library bindings 可供您学习——从原始示例来看,您正试图在 SQLite 之上创建一个 CRUD 视图界面。