Clarity 智能合约程序开发教程|理解私有函数和只读函数 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gitandgit
V2EX    区块链

Clarity 智能合约程序开发教程|理解私有函数和只读函数

  •  
  •   gitandgit 2021-09-26 11:40:37 +08:00 903 次点击
    这是一个创建于 1551 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原英文文档链接: https://book.clarity-lang.org/ch05-02-private-functions.html

    只读函数

    只读函数可以被合约程序本身调用,也可以从部调用。它们可以返回任何类型,就像私有函数一样。

    顾名思义,只读函数只能执行读操作。您可以读取数据变量和映射,但不能写入它们。只读函数也可以是纯函数式的;也就是说,根据输入计算一些结果并返回它。代码可以这样写:

    (define-read-only (add (a uint) (b uint)) (+ a b) ) (print (add u5 u10)) 

    代码还可以这样写:

    (define-data-var counter uint u0) (define-read-only (get-counter-value) (var-get counter) ) (print (get-counter-value)) 

    然而,下面是一个错误的代码示例:

    (define-data-var counter uint u0) (define-read-only (increment-counter) (var-set (+ (var-get counter) u1)) ) (print (increment-counter)) 

    如您所见,分析告诉我们它在只读函数中检测到写入操作:

    分析错误:只读语句,检测到写操作( define-data-var counter uint u0 )

    不过不用担心,没有严重的后果。如果分析失败,则合约程序无效,这意味着它无法部署在网络上。

    使只读函数非常有趣的一件事是,它们可以在不实际发送转账交易的情况下被调用!通过使用只读函数,您可以读取应用程序的合约状态,而无需您的用户支付交易费用。 Stacks.js官方钱包浏览器扩展 支持调用内置的只读函数。您现在可以使用 Stacks Sandbox 亲自尝试一下。找到一个带有只读函数的合约程序,直接调用。完全免费!

    练习题:创建一个只读函数,返回给指定主体用户的计数器值,如果主体用户不存在于映射中,则返回 u0 。

    (define-map counters principal uint) (map-set counters 'ST1J4G6RR643BCG8G8SR6M2D9Z9KXT2NJDRK3FBTK u5) (map-set counters 'ST20ATRN26N9P05V2F1RHFRV24X8C8M3W54E427B2 u10) (define-read-only (get-counter-of (who principal)) ;; Implement. ) ;; These exist: (print (get-counter-of 'ST1J4G6RR643BCG8G8SR6M2D9Z9KXT2NJDRK3FBTK)) (print (get-counter-of 'ST20ATRN26N9P05V2F1RHFRV24X8C8M3W54E427B2)) ;; This one does not: (print (get-counter-of 'ST21HMSJATHZ888PD0S0SSTWP4J61TCRJYEVQ0STB)) 

    私有函数

    私有函数的定义方式与公共函数相同。不同的是它们只能被当前的合约程序调用。它们不能被其他智能合约程序调用,也不能通过发送转账交易直接调用。私有函数可用于创建实用程序或辅助函数以减少代码重复。如果您发现自己在多个位置有重复类似的表达式,那么值得考虑将这些表达式转换为单独的私有函数。

    下面的合约程序只允许合约所有者通过两个公共函数更新 recipients 地图。不必重复地检查 tx-sender,而是将其抽象为自己的私有函数,称为 is-valid-caller 。

    (define-constant contract-owner tx-sender) ;; Try removing the contract-owner constant above and using a different ;; one to see the example calls error out: ;; (define-constant contract-owner 'ST20ATRN26N9P05V2F1RHFRV24X8C8M3W54E427B2) (define-constant err-invalid-caller (err u1)) (define-map recipients principal uint) (define-private (is-valid-caller) (is-eq contract-owner tx-sender) ) (define-public (add-recipient (recipient principal) (amount uint)) (if (is-valid-caller) (ok (map-set recipients recipient amount)) err-invalid-caller ) ) (define-public (delete-recipient (recipient principal)) (if (is-valid-caller) (ok (map-delete recipients recipient)) err-invalid-caller ) ) ;; Two example calls to the public functions: (print (add-recipient 'ST1J4G6RR643BCG8G8SR6M2D9Z9KXT2NJDRK3FBTK u500)) (print (delete-recipient 'ST1J4G6RR643BCG8G8SR6M2D9Z9KXT2NJDRK3FBTK)) 

    另一个很好的好处是:定义私有函数可以降低整体函数的复杂性。大型公共函数可能更难维护,更容易出现开发人员错误。将这些功能拆分为公共函数和一些较小的私有函数可以缓解这些问题。

    私有函数可以返回任何类型,包括响应,尽管会返回 ok 或 err, 这并不会影响链的具体化状态。

    练习题:写一个名为“is-valid-caller”的私有函数,该函数根据 tx-sender 是否是授权主体用户之一,返回 true 或 false 。

    (define-constant err-invalid-caller (err u1)) (define-map authorised-callers principal bool) (define-map recipients principal bool) (map-set recipients tx-sender true) (map-set authorised-callers 'ST20ATRN26N9P05V2F1RHFRV24X8C8M3W54E427B2 true) (define-private (is-valid-caller (caller principal)) ;; Implement. ) (define-public (delete-recipient (recipient principal)) (if (is-valid-caller tx-sender) (ok (map-delete recipients recipient)) err-invalid-caller ) ) (print (delete-recipient tx-sender)) 
    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1176 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 17:38 PVG 01:38 LAX 09:38 JFK 12:38
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86