Leo 语言 Hello World 的学习心得
先打个强心针,我目前涉及的行业只能说和之前所学的大不相同——区块链。
今天接到一个任务:将 Leo 语言学会,然后短时间内创建一个简单的区块链框架。以下文章作为今天的学习心得。项目已经开源到 hubei-xhjy 的仓库中,需要的同学自取。
安装 Leo
这个过程主要看网络环境,我下了半小时左右,期间利用时间来查询一些相关资料及文档,我的环境是 MacOS,需要安装 git 和 rust。git 的安装很简单(Mac OS 自带),而 rust 则需要执行以下命令
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
通过以下指令来查看环境是否安装成功
git --version |
然后在你习惯的 working directory (比如说我 cd ~/src/
) 克隆 Leo 项目,并安装 Leo
git clone https://github.com/AleoHQ/leo |
执行完这一步之后,将会在 ~/.cargo/bin/leo
创建一个可执行文件。
可以通过在终端运行以下指令来验证安装是否成功
leo |
代码高亮
我使用的开发环境是 VSCode,直接在应用商店搜寻 Leo
然后安装第一个插件(作者:aleohq
,识别号:aleohq.leo-extension
)
创建第一个 Leo 项目
回到你的 working directory(这一步很重要!),通俗点就是 terminal 的位置要在你平时放代码的目录。leo 创建的项目和其他编程环境一样(如 Node JS),会创建一个项目文件夹。
然后执行以下指令
leo new hello |
这时候会创建一个 leo 项目目录,并将其命名为 hello,然后我们进入 hello 文件夹中。里边的文件列表是这样的:
hello/ |
执行项目
因为创建的项目中已经有一个写好的 example 文件,所以我们可以通过以下指令编译并运行程序
leo run main |
一些细节上的内容可以直接查看官方文档,由于篇幅限制就不再赘述
代码解释
源程序给出了这么一段代码
// The 'hello' program. |
hello.aleo
是我们的程序名称,他必须和我们的 Manifest 文件中的program
字段相对应。transition
的意思是构建了一个 transition 函数,目前尚未对transition
函数有了解,但是本文后面有对该函数的猜想- 然后
main
函数中携带了两个参数: public a: u32
:- u32 初步判断为其他编程语言中
unsigned int32
类型 - public 指的是这个函数的可见性是公共的。
- u32 初步判断为其他编程语言中
b: u32
:- 这个是私有变量,默认变量作用域就是私有变量
-> u32
:- 这个写法说明 main 函数返回一个 u32 的值
- 然后
- 理论上
main
可以是任何一个英文单词(在本文后面会讲解关于:关键字、输入文件等相关概念) - 函数中使用
let
语法定义了一个 c 变量,类型也为 u32(和我们的返回值相同)- 它的值就是
a + b
。由此可见我们的 main 函数执行的功能就是两数相加
- 它的值就是
- 最后再通过
return
语法返回 c 变量。
官方提到,由于开发者也是人类,也会犯错,所以他们将该编程语言设计成强类型编程语言。
但是我在这里吐槽一下,这种类型的语法未免也太魔鬼了吧。第一眼看到这个写法我的直觉是好复杂。
文件输入
我们来观察 hello.in
文件,这将是我们 hello.aleo
程序的输入。
暂时不知道作者这么操作的意图(或者说输入文件存在的意义)是什么,正如我一开始所说,区块链是我最近才深入接触的领域。
[main] |
可以看到,[main]
代指以下的信息是会传递给 main 函数的,其中传递:public a: u32
(这个值和上面函数定义的值相同),而它的值为:1u32
。如果将其置换为其他编程语言表示,应该是这样:
public UInt32 a = 32; |
换言之,它的数据表达应该是 【值 类型】。
验证猜想
有了上面的实操经验,接下来我来验证一些我在学习中的猜想
猜想:一个 program 中可以有多个函数
因为我注意到我们是通过 leo run main
指令来执行程序,而非 leo run
或者 leo run hello.aleo
。这样我猜测 leo run main
其实是执行 main
函数。这就是说,一个 Leo 程序可以拥有多个 transition 函数。于是我增加了这么一句:
transition substract(public a: i32, b: i32) -> i32 { |
可以注意到:我增加了一个 substract
函数,参数需求和 main 函数几乎相同,不同的是数据类型由 u32
变为 i32
。也就是一般编程语言中的 int
。返回值也同样变成了整型。而函数执行的是 a - b
并将其返回。
我们先不急着执行这个函数,别忘了我们还需要去定义函数的输入,现在渠道 hello.in
文件。
猜想:hello 文件中可以对不同的函数定义不同的输入
上面我们定义了一个 [main]
函数的输入,那么在这里,函数中我们创建了
[substract] |
因为我们创建的是 substrate 函数,所以这里也需要写上 [substract]
,让程序知道这个输入是给 substract 函数使用的。
同样的,我们要给对应的变量定义正确的数据类型,在这里是 i32
。
猜想:除了 main 函数,我们也可以执行别的函数
上面学的是 leo run main
,然后它执行的是 main 函数嘛。那我们可以通过修改 run 之后的值,来执行别的函数,如:
leo run substract |
执行这段指令之后,会执行我们自定义的 substract 函数。并执行减法输出。
猜想:leo 程序的执行顺序
当我们执行 leo run xxx
时,它会运行 xxx
函数,然后再去 input 文件夹找到对应 [xxx]
的输入,并执行计算然后输出结果。
验证过程中的意外收获
关键字
为什么我们创建的是 substract
函数而不是 sub
函数。我已经尝试过了,最后得出的结论:
在执行
leo run xxx
之后 leo 将会把我们的源码打包成aleo
。一种类似汇编语言的代码,位于build/
文件夹中。而sub
正是 “汇编” 语言中的其中一个关键词。所以我们不能通过sub
作为函数。
如果在定义用户标识符使用关键字,那么 leo 会报出:Failed to parse string
报错。
总结
对于 Leo 语言,可能是新兴编程语言的缘故,想要做出差异化。反而使得代码更加的晦涩难懂。何况这种直接转义成“汇编语言”的骚操作,导致一些代码会变得更加冗余。后续的文章中将会对区块链的各种开发语言进行学习与比较。