V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gitandgit
V2EX  ›  区块链

Clarity 智能合约开发语言教程| try!函数和 Unwrap 函数使用

  •  
  •   gitandgit · 2021-10-06 15:29:14 +08:00 · 576 次点击
    这是一个创建于 1154 天前的主题,其中的信息可能已经有所发展或是发生改变。

    英文原文档: https://book.clarity-lang.org/ch06-02-try.html

    try!函数采用 optional 或 response 类型,并将尝试解开它。解开是提取内部值并返回它的动作。以下面的例子为例:

    (try! (some "wrapped string"))
    
    

    它将解开 some 并返回内部的“wrapped string”。

    try! 只能成功解开 some 和 ok 的值。如果它收到 none 或 err,它将返回输入值并退出当前控制流。换句话说:

    • 如果它收到一个 none,它返回一个 none 并退出。

    • 如果它收到一个 err,它返回那个 err,并退出。它不会打开里面的值!

    下面的测试函数允许我们试验这种行为。它将响应类型作为输入传递给 try!。然后我们将使用 ok 和 err 调用该函数并打印结果。

    (define-public (try-example (input (response uint uint)))
        (begin
            (try! input)
            (ok "end of the function")
        )
    )
    
    (print (try-example (ok u1)))
    (print (try-example (err u2)))
    
    

    第一个打印结果为( ok "end of the function"),如 begin 表达式的末尾所示。但是通过 err 的第二个调用将返回原始值 (err u2)。尝试!因此,函数允许您传播发生在子调用中的错误,我们将在有关中间人响应的章节中看到更多的用法。

    Unwrap 函数

    其他 unwrap 函数都是以稍微不同的方式退出当前控制流的变体。

    unwrap! 将 optional 或 response 作为第一个输入,将抛出值作为第二个输入。它遵循与 try! 相同的解包行为! 但不是传播 none 或 err 而是返回 throw 值。

    (unwrap! (some "wrapped string") (err "unwrap failed"))
    
    

    unwrap-panic 接受一个输入,它可以是一个 optional 或 response 。如果它无法解包输入,它会抛出一个运行时间错误并退出当前流。

    (unwrap-panic (ok true))
    
    

    unwrap-err-panic 是 unwrap-panic 的相对应者,如果输入是 err,则解包,否则抛出运行时间错误。

    (unwrap-err-panic (err false))
    
    

    理想情况下,除非绝对必须,否则不应使用 -panic 变体,因为它们在失败时不会提供任何有意义的信息。一笔转账交易将返回一个模糊的“运行时间错误”,用户和开发人员就需要弄清楚到底出了什么问题。

    Unpacking assignments

    在使用 let 分配局部变量时,unwrap 函数特别有用。如果存在,您可以解包并分配一个值,如果不存在则退出。它使用 maps 和 lists 函数来执行。

    ;; Some error constants
    (define-constant err-unknown-listing (err u100))
    (define-constant err-not-the-maker (err u101))
    
    ;; Define an example map called listings, identified by a uint.
    (define-map listings
        {id: uint}
        {name: (string-ascii 50), maker: principal}
    )
    
    ;; Insert some sample data
    (map-set listings {id: u1} {name: "First Listing", maker: tx-sender})
    (map-set listings {id: u2} {name: "Second Listing", maker: tx-sender})
    
    ;; Simple function to get a listing
    (define-read-only (get-listing (id uint))
        (map-get? listings {id: id})
    )
    
    ;; Update name function that only the maker for a specific listing
    ;; can call.
    (define-public (update-name (id uint) (new-name (string-ascii 50)))
        (let
            (
                ;; The magic happens here.
                (listing (unwrap! (get-listing id) err-unknown-listing))
            )
            (asserts! (is-eq tx-sender (get maker listing)) err-not-the-maker)
            (map-set listings {id: id} (merge listing {name: new-name}))
            (ok true)
        )
    )
    
    ;; Two test calls
    (print (update-name u1 "New name!"))
    (print (update-name u9999 "Nonexistent listing..."))
    
    

    找到注释的地方 ;; The magic happens here 。在 update-name 函数中并仔细研究下一行。这是发生的事情:

    • 它定义了一个名为 listing 的变量。

    • 该值将等于 get-listing 函数的解包结果。

    • get-listing 返回 map-get? 的结果,它是 some 列表或者 none 。

    • 如果解包失败,unwap!以 err-unknown-listing 退出。

    因此,第一个测试调用将成功并返回( ok true ),而第二个调用将出错,并返回( err u100 )( err-unknown-listing )。

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1089 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 19:16 · PVG 03:16 · LAX 11:16 · JFK 14:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.