打印
[资料干货]

通过示例学习rholang(上部:课程0-2)

[复制链接]
528|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
通过例子和实践来学习rho语言。下面的例子和练习都很值得去运行、阅读、修改和完善。修改练习和教程中任何你感到有意思的代码,这样能够获得最好的学习效果。该教程包含了rho语言最常见以及最重要的特性,足以让开发者快速入门。
课程0 -- 开发环境
配置你的开发环境
为了可以运行这个教程里面的rholang代码,你需要一些开发环境。 这不是一个会让你感到疲惫的rholang开发工具或者技术栈。 然而它展示了一些基本的开发环境给你开始。
网上编译器
RChain社区的成员提供了一个基于公共网站的在线rholang编译器。 这个工具非常有前途,也是一种入门的简单方式。 但是它还是开发节点,有时候会不稳定。
本地节点
真正正确运行rholang代码的方法是在通过启动你自己本地机子的RNode然后使用它的rholang编译器。 首先你要为你自己的平台安装 RNode
对于初学者,这里有详细的一步一步指导你怎么使用AWS 或者Docker启动你的节点.
一旦你的RNode安装好了,你可以运行基本的独立节点。
$ rnode run -s -n
在单独的终端里,你可以在REPL模式下一次执行一行rholang。
$ rnode repl
╦═╗┌─┐┬ ┬┌─┐┬┌┐┌ ╔╗╔┌─┐┌┬┐┌─┐ ╦═╗╔═╗╔═╗╦
╠╦╝│ ├─┤├─┤││││ ║║║│ │ ││├┤ ╠╦╝║╣ ╠═╝║
╩╚═└─┘┴ ┴┴ ┴┴┘└┘ ╝╚╝└─┘─┴┘└─┘ ╩╚═╚═╝╩ ╩═╝
rholang $ Nil
Deployment cost: CostAccount(0,Cost(0))
Storage Contents:
for( x0, x1 <= @{Unforgeable(0x01)} ) { Nil } | for( x0, x1, x2, x3 <= @{"secp256k1Verify"} ) { Nil } | for( x0, x1 <= @{"sha256Hash"} ) { Nil } | for( x0, x1 <= @{Unforgeable(0x03)} ) { Nil } | for( x0, x1, x2, x3 <= @{"ed25519Verify"} ) { Nil } | for( x0, x1 <= @{"blake2b256Hash"} ) { Nil } | for( x0 <= @{Unforgeable(0x02)} ) { Nil } | for( x0 <= @{Unforgeable(0x00)} ) { Nil } | for( x0, x1 <= @{"keccak256Hash"} ) { Nil }
rholang $ @"world"!("hello")
Deployment cost: CostAccount(5,Cost(64))
Storage Contents:
@{"world"}!("hello") | for( x0, x1 <= @{Unforgeable(0x01)} ) { Nil } | for( x0, x1, x2, x3 <= @{"secp256k1Verify"} ) { Nil } | for( x0, x1 <= @{"sha256Hash"} ) { Nil } | for( x0, x1 <= @{Unforgeable(0x03)} ) { Nil } | for( x0, x1, x2, x3 <= @{"ed25519Verify"} ) { Nil } | for( x0, x1 <= @{"blake2b256Hash"} ) { Nil } | for( x0 <= @{Unforgeable(0x02)} ) { Nil } | for( x0 <= @{Unforgeable(0x00)} ) { Nil } | for( x0, x1 <= @{"keccak256Hash"} ) { Nil }
当你运行更多行数的rholang代码时候,你可以使用RNode的eval模式来执行代码。
$ rnode eval intersection.rho
Evaluating from intersection.rho
Result for intersection.rho:
Deployment cost: CostAccount(39,Cost(1132))
Storage Contents:
@{Unforgeable(0xb19519ab773d1ec4ce96f1b71b748552e4a084dfc9942371717f5cb87e818879)}!(@{"name"}!(Nil)) | @{Unforgeable(0xb19519ab773d1ec4ce96f1b71b748552e4a084dfc9942371717f5cb87e818879)}!(@{"age"}!(Nil)) | @{"world"}!("hello") | for( x0, x1 <= @{Unforgeable(0x01)} ) { Nil } | for( x0, x1, x2, x3 <= @{"secp256k1Verify"} ) { Nil } | for( x0, x1 <= @{"sha256Hash"} ) { Nil } | for( @{{@{"name"}!() | _ /\ @{"age"}!() | _}} <= @{Unforgeable(0xb19519ab773d1ec4ce96f1b71b748552e4a084dfc9942371717f5cb87e818879)} ) { @{Unforgeable(0x00)}!("Both name and age were in the data") } | for( x0, x1 <= @{Unforgeable(0x03)} ) { Nil } | for( x0, x1, x2, x3 <= @{"ed25519Verify"} ) { Nil } | for( x0, x1 <= @{"blake2b256Hash"} ) { Nil } | for( x0 <= @{Unforgeable(0x02)} ) { Nil } | for( x0 <= @{Unforgeable(0x00)} ) { Nil } | for( x0, x1 <= @{"keccak256Hash"} ) { Nil }
有一些RNode的输出会出现在你运行代码的同一个终端。但是其它一些代码输出会直接出现在第一个终端。 所以在你熟悉什么输出出现在哪里前请确定好检查两边的终端。
Cryptofex IDE
一个叫做cryptofex 的开发环境已经进入了alpha版本。 Cryptofex可能最后最好的开发rholang的地方,但是现在还是很早期的软件。 Cryptofex提供rholang语法高亮特性并且可以在RChain集成节点上检测dApps。 IDE同时也提供环境创建和测试在以太网上,私人测试网上和单独模式的EVM上的智能合约。
课程1 -- 发送与标准输出(stdout)
发送与标准输出(stdout)
说声Hello

"Person waiving hello"
编程界有一个存在已久的传统——输出"Hello World"应该是你学习的第一个程序。下面是一个在屏幕上输出"Hello World"的最简单例子。
hello.rho
练习
请让程序输出"Rholang rocks!" 而不是 "Hello World"。
练习
尝试将"stdout"替换为别的语句。会得到什么结果?
尝试一下这个有趣的通道名称@"someChannel". 这里可以比较随意。请让程序在屏幕上输出 "Sup World"。
标准输出(stdout)到底是什么东西


Channels are like mailboxes for sending messages
rho语言的核心是通道(channel,下面都称为通道)通信. 通道是你可以用来发送和接收消息的通信线路。你可以使用!字符来在通道中发送消息。


Redo this diagram!
stdout 是一个特殊的通道,用于将文本发送至"标准输出",通常指你的电脑屏幕。正因为它的特殊,我们不得不将它写在第一段学习的代码里面。
使用其他通道


Sent messages wait to be received here in "message purgatory"... JK, it's called the "tuplespace"
实际上你可以在很多通道中发送消息,而非只有stdout。 但其它通道不像 stdout 他们不会在屏幕上显示。
tupleSpace.rho
那么,在其他通道中的消息将被发送至哪里?哪里都不会去!这些消息暂时哪儿都不去,这些消息会继续待在通道内,等待其他人去取出它们。我们将在下一课程中学习如何获取这些消息。同时,消息滞留所在的地方,我们称为 "元组空间"。
请确保你的信息保留在元组空间里。你应该会看到像下面的信息。
Storage Contents:
@{"RandoChannel"}!("This won't be on the screen") | for( x0, x1 <= @{Unforgeable(0x01)} ) { Nil } | for( x0, x1, x2, x3 <= @{"secp256k1Verify"} ) { Nil } | for( x0, x1 <= @{"sha256Hash"} ) { Nil } | for( x0, x1 <= @{Unforgeable(0x03)} ) { Nil } | for( x0, x1, x2, x3 <= @{"ed25519Verify"} ) { Nil } | for( x0, x1 <= @{"blake2b256Hash"} ) { Nil } | for( x0 <= @{Unforgeable(0x02)} ) { Nil } | for( x0 <= @{Unforgeable(0x00)} ) { Nil } | for( x0, x1 <= @{"keccak256Hash"} ) { Nil }
同时做两件事


Rather than following an ordered list, all ingredients are added concurrently. Looks delicions
在rholang中,我们不会告诉计算机做完一件事,再到另一件。相反,我们会告诉它需要做的所有事情,然后"并行地"执行它们,或者一次性全部执行。
parallel.rho
| 的发音是 "parallel", 可简称为 "par"。
练习
向"pizza shop"通道发送消息"1 large pepperoni please"。
练习
向"Mom's Phone"通道发送"Hi Mom"。
练习
用一个程序在屏幕上输出两个消息,"Rick"和 "Morty"。
小测试
stdout!("Programming!") 将在屏幕上输出什么?
Programming!
stdout!
Nothing
@"what"!("Up") 在什么通道上发送消息?
@"Up"
@"what"
what
rholang会先执行哪一条语句?
@"stdout"!("Dogs")
|
@"stdout"!("Cats")
输出 "Dogs"
输出 "Cats"
都不。 它们是并行的 PS. 有一个特殊的通道 stderr. 请尝试一下看看往这个通道发送消息,会发生什么? 有什么区别?
课程2 -- 接收
消息检查

// Dear future self, keys in freezer because...
在上一章我们学习了如何发送消息。现在是时候学习如何接收消息了。常规语法如下:
for(message <- channel){ // Do something here}
顺便提一下, // 用于标示注释。 //后面的内容程序并不会运行。写好注释可以有利于其他开发者(包括你自己)阅读代码,并了解代码的意图,其他读你代码的开发者会感激你写注释的。
通信事件


Pizza shop can receive messages on its channel.
下面的代码使用披萨店的通道发送了一个消息,披萨店收到了它。pizza店通过将消息打印至标准输出来表明其已收到。
pizzaOrder
练习
将上述消息发送至一个不同的通道,如@"coffeShop". 消息会被接收端打印出来吗? 还是东西留在了元组空间里么?
Let's hit up the coffee shop.
练习
记住,在rholang中,任何事情都是并行地而非按顺序地执行。如果我们把接收信息的代码放在前面,那么披萨店的代码仍可执行。尝试一下吧。
元组空间污染
如果你遇到了旧数据滞留在元组空间并会对后面的代码执行有影响,你需要清空你的元组空间。最简单的方式是删除你的数据目录.rnode
使用上述方法清空元组空间已经过时了。一个更好的方法是防止它一开始被旧数据污染。我们可以通过修改最上面的new代码段来实现。
旧的方案
new stdout(rho:io:stdout) in { @"world"!("Welcome to RChain") }
尝试下面新的方案
new world, stdout(rho:io:stdout) in { world!("Welcome to RChain") // No more @ or " " }
我们将在“不可伪造的names”的课程中讲解它的原理。现在你不需要每次都重置通道。
发送前接收


Rather than the message appearing first, then someone receiving it, Greg is trying to receive first. Hopefully someone will send him a message so he can have a comm event.
当发送和接收同时存在于通道时,这被称为通信事件,或称为"comm event"。
不像普通邮件那样必须被发送,对方才能被接收,在rholang中,上述两个事件可以以任何顺序发生或者同时发生。这类似于可以先接收消息,再发送它。每当发送和接收共存时,就会触发通信事件。
合约


The poor chef is too busy making sure he can receive orders to take care of his pizza.
我们的披萨店例子很好地说明了通信事件,但期望每次有新的订单时,披萨店都能自动发出一个新的接收来处理它们,这并不现实。
幸运地是,我们可以只部署一次代码,然后每次接收到它的消息时都执行一次。这类代码称为“智能合约”。让我们看一个比披萨店更高级但相似的例子--咖啡店。
coffeeShop.rho
练习
在咖啡店点第二杯饮料
练习
更改上面例子的确认消息
一般来说,下列哪一个会第一个发生?
发送,因为它与普通邮件的工作原理一样。 接收,因为以该方式运行的代码更快。 发送或接收都可以最先发生,或者同时。 接收,因为rohlang是并行的。 都不。直接触发通信事件(comm event)。
练习
通道被命名为 @"coffeeShop"。将它更名为你所选择的特定咖啡店的名称。然后使用我们最近学到的new来修改代码
Persistent For
实际上,在rholang中有两种不同的语法来表示持续从通道取出信息。我们刚刚学习contract语法。下面的用for语法的代码是等价的。
contract @"coffeeShop"(order) = { for(order <= @"coffeeShop") { 注意,上述代码与正常的 for 不同,因为它使用了双划线 <= 而不是单划线 <-. for和contract是有不同的地方的,我们会在讨论区块链的时候讨论到他们的区别。现在你可以将它们当做同一功能。
练习
用持久的for语法而不是"contract"语法来写一个想咖啡店这样的披萨店合约。尝试自己从头写一次整个代码,这样会让你更容易记清语法。
下面哪一项是与其他两项不同的?
for (a <- b){}
contract b(a) = {}
for (a <= b){}
哪一个发送语句会与for (message <- @"grandmasSnapChat"){Nil}对应产生一个通信事件 ?
grandmasSnapChat!("Hi Grandma")
@"grandmasSnapChat"!("Glad you're snapping Grandma")
for("Here's a snap for you g'ma" <- @"grandmasSnapChat")

17.png (61.65 KB )

17.png

16.png (34.66 KB )

16.png

15.png (28.94 KB )

15.png

13.png (137.6 KB )

13.png

14.png (135.6 KB )

14.png

11.png (197.2 KB )

11.png

12.png (158.98 KB )

12.png

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

7

帖子

0

粉丝