如何将价值从红色/系统传递到红色? [英] How to pass value from Red/System to Red?

查看:90
本文介绍了如何将价值从红色/系统传递到红色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将在Red/System中生成的值传递给Red.我发现了文档,但没有找到如何使用它的示例.这是我的代码:

I need to pass the value that I generate in Red/System to Red. I discovered docs but did not find an example of how to use it. Here is my code:

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,我要用红色/系统部分的数据填充.

my-red-block here is Red block that I want to fill with data from Red/System part.

https://github.com/meijeru/red.specs-public/blob/master/specs.adoc#routine-type

推荐答案

简介

Red使用数据堆栈传递参数并返回结果.堆栈上的每个值都是一个盒装结构,大小为4个平台指针,并且可以包含对外部缓冲区的引用;这意味着您需要构造它们并将它们压入堆栈,尽管如果返回它们,某些原始的Red/System类型(例如logic!integer!)会自动升级.

Intro

Red uses data stack to pass arguments and return the result. Each value on the stack is a boxed structure 4 platform pointers in size and may contain references to external buffers; this means that you need to construct them and push them on a stack, although some primitive Red/System types (like e.g. logic! or integer!) are promoted automatically if you return them.

但是,在您的情况下,不需要使用堆栈,因为您想直接在块中分配值.具有低级编程经验,并具有红色/系统和红色的知识运行时API 是此任务的必要先决条件.因此,让我们以您的示例为例,并逐步进行操作.

In your case, however, usage of the stack is not necessary, as you want to allocate values directly in a block. Experience with low-level programming and knowledge of Red/System with Red runtime API are the essential prerequisites for this task. So let's take your example and go through it step by step.

  1. 您有一个块,并且想要向其附加两个值,123"Hello".假设您要从Red/System中执行此操作.为此,我们需要编写一个例程.
  1. You have a block and you want to append two values to it, 123 and "Hello". Suppose you want to do that from Red/System. For that, we need to write a routine.
list: []
foo: routine [][...]

  • 在此例程中,您需要掌握list字引用的块.做到这一点的困难方法是实例化一个符号并通过其ID在全局上下文中查找值:

  • Inside this routine, you need to get hold of the block referenced by list word. The hard way to do that is to instantiate a symbol and look up the value in global context by its ID:

    list: []
    
    foo: routine [
        /local
            blk [red-block!]
    ][
        blk: as red-block! _context/get-global symbol/make "list"
    ]
    

    list作为参数会更合理,但出于教育目的,我将其保持原样.

    Passing list as an argument would be more reasonable, but I'll keep it as-is for educational purposes.

    现在,我们要将123附加到此块.有block/rs-append函数可以做到这一点,但是它接受一个带框的参数.因此,我们需要先将123自己装箱.

    Now we want to append 123 to this block. There's block/rs-append function that does exactly that, but it accepts a boxed argument. So we need to box 123 ourselves first.

    1. 是装箱整数的方式看起来像;如您所见,它只是32位123值+插槽标头和填充.我们可以自己构造和初始化这样的结构:
    1. This is how boxed integer looks like; as you can see, it's simply 32-bit 123 value + slot header and padding. We can construct and initialize such structure ourselves:
    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!并返回一个装箱的red-integer!结构:

    Fortunately, Red runtime already covers that with integer/box function that takes a Red/System integer! and returns a boxed red-integer! struct:

    integer/box 123
    

  • 现在,我们需要将此装箱的整数附加到块中.直观地,我们可以检查 block.reds定义和找到符合我们要求的block/rs-append:

  • Now we need to append this boxed integer to a block. Intuitively, we can check block.reds definitions and find block/rs-append that matches our requirements:

    block/rs-append blk as red-value! integer/box 123
    

    在此步骤的最后,我们有:

  • At the end of this step, we have:

    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!进行转换.

  • Now we want to append a "Hello" string, but first we need to construct it. Red strings support UTF-8 and use fixed-size internal encoding (1, 2 or 4 bytes per character, depending on the maximum codepoint size); that's a lot of details to get right manually, so the typical way of constructing such string is by converting it from 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部件(在我们的情况下为c-string!中的red-string!)构造(即加载")高级Red值.由于我们要在块的尾部构造它,因此可以使用string/load-in:

    Examining string! datatype runtime definitions you will notice some handy wrappers prefixed with load; this is a convention indicating that such function can be used to construct (i.e. "load") high-level Red value from low-level Red/System parts, in our case red-string! from c-string!. Since we want to construct it at the tail of a block, we can use string/load-in:

    str: "Hello"
    string/load-in str length? str blk UTF-8
    

    请注意,我使用length?而不是size?来排除NUL终止的字节.

    Note that I use length? instead of size? to exclude NUL-terminated byte.

    结论

    就是这样.在一天结束时,我们可以整理一下代码并检查它是否完全有效:

    Conclusion

    This is it. At the end of the day we can tidy the code a little bit and check if it works at all:

    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执行生成的二进制文件会给我们带来预期的结果:

    Compiling this script in release mode and executing the resulting binary from the shell gives us the expected result:

    [123 "Hello"]
    


    毋庸置疑,这一切对新手来说都是不知所措:尽管Red和Red/System都拥有不错的文档和学习资源,但它们之间通过运行时交互的桥接却是未知的领域.这样做的原因是因为项目在不断发展并且API尚未稳定,因此,现在不是记录该项目并将具体设计决策付诸实践的合适时机.经验丰富的开发人员可以很快掌握其原理,但这需要对Red的评估模型有扎实的概念理解-这些基础知识是您首先需要掌握的.


    Needless to say, this all might look quite overwhelming to newcomers: while both Red and Red/System have decent documentation and learning resources, their bridging via runtime interaction is uncharted territory. The reason for that is because the project is evolving and the API is not yet stabilized, so, at the moment, it's not the right time to document it and cast the design decisions in stone. Experienced developers can get their bearings pretty quickly though, but that requires a solid conceptual understanding of Red's evaluation model -- these basics are what you need to master first.

    还有很多库绑定,您可以从中学习- -从原始示例来看,您正在尝试在SQLite之上创建CRUD View界面.

    There's also a plethora of library bindings that you can learn from -- judging by the original example, you are trying to make a CRUD View interface on top of SQLite.

    这篇关于如何将价值从红色/系统传递到红色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆