作业
把 Message 类型改为一个记录结构,并在里面添加 time 字段,记录发消息的时间。
要求:
1)提交主程序源代码并部署应用到主网提交链接(2 分)
2)正确定义了新的 Message 的记录结构 (1 分)
3)在 post 方法中,创建了新 Message 并记录了当前时间
2)理解了记录结构的定义就能完成
3)查看阅读time的使用方法
修改 posts 和 timeline 方法,仅返回指定时间之后的内容:
import Time “mo:base/Time”;
func posts(since: Time.Time): async [Message] {…};
func timeline(since: Time.Time): async [Message] {…};
要求:
1)提交主程序源码并部署应用到主网提交链接(2 分)
2)正确实现了按指定时间删选消息的功能 (2 分)
让原本无输入直接返回数组,变成输入一个形参返回一个数组,筛选使用if语句就可以实现
如果关注对象很多,运行 timeline 就会比较慢,有什么办法可以提高效率?
要求:
1)用文字描述一个解决方案 (1分)
2)可行性评估(1分)
结构
模式匹配
record记录结构和variant枚举
//声明一个结构
let person = {
name = "Jacky Chan";
age = 67 ;
};
//声明一个函数
func f() :{name:Text; age: Nat} {
person;
};
意思是返回两个参数,一个是字符串类型的name,一个是自然数型的age
:是说明函数返回的类型
枚举
枚举类型用于声明一组命名的常数
//声明一个枚举
type Gender = {
#male;
#female;
};
//声明一个结构
let person = {
name = "Jacky Chan";
age = 67;
gender = #male;
};
元组
元组:不能改变的只读列表(解释参考之python),序列
//声明一个元组
let x : (Int, Bool) = (10,false);
//调用一个元组
let y : Bool = x.1;
}
//声明一个类型
type Gender = {
#male;
#female;
#unspecified:{retire_Age:Nat};
};
//声明一个函数,参数为person,返回类型为bool
func retired(person:Person) :Bool {
switch (person.Gender) {
case(#male) (person.age >= 60);
case(#female) (person.age >=55 );
//调用类型里的字段的值
case(#unspecified({retired_age})) (persin.age>=retire_age);
}
};
option类型
func retired(person:Person) : ?Bool {
switch (person.Gender) {
case(#male) ?(person.age >= 60);
case(#female) ?(person.age >=55 );
case(#unspecified) null;
}
};
option类型:?boll,?Nat
option值:null,?true,?12
函数
从定义域domain到值域range的映射关系
func dec(a:Int) :Int{a-1};
匿名函数
func 后面没有函数名字,只有形参和返回类型和函数内部
let dec :Int -> Int = func(a) {a-1};
let inc = func(a:Nat) :Nat{a+1};
<A>的意思是函数接受一个可变类型的类型参数
public func init<A>(size :Nat,initVal :A):[var A] {
Prim.Array_init<A>(size,initVal);
};
public func tabulate<A>(size :Nat, gen : Nat->A) :[A] {
Prim.Array_tabulate<A>(size,gen);
};
Nat->A:意思是gen参数接受的是一个函数参数,通过计算得到的,通过Nat到A
let arr = Array.init<Int>(5,42);
let brr = Array.tabulate<Nat>(100,func(i){i});
let crr = Array.tabulate<Int>(100,func(i){i*2});
Object对象
object counter {
var count =0;
public func inc() {count +=1};
public func read() : Nat{count};
public func bump() : Nat{
inc();
read();
};
};
//对象内,成员函数可互相调用
counter.inc()
//调用counter内的成员函数
//Counter这个object是什么类型呢?
//自定义了一个类型
type Counter = {
//输入空,返回空
inc:()->();
//输入空,返回自然数
read:()->Nat;
//输入空,返回自然数
bump:()->Nat;
}
actor是一种特殊的object
//actor声明
actor counter {
var count =0;
public shared func inc() :async() {count +=1};
public shared func read() :async Nat{count};
public shared func bump() :async Nat{
count +=1;
count;
};
};
type Counter =actor {
inc : shared()->async();
read: shared()->async Nat;
bump: shared()->async Nat;
};
//shared可以把函数当作参数传递给其他actor,必须是async异步函数
await是怎么个用法
首先是会有一个async的函数,会异步返回一个值
调用async的函数都需要await
问题与解决
编译检查
dfx build --check
需要一个新的list
那要实现
public shared func posts() :async [Message] {
List.toArray(messages);
};
调用函数canister里的函数
dfx canister call canister名字 函数名字 “(实参)”
dfx canister call microblog2 follow "(principal \"$(dfx canister id microblog)\")"
让microblog2跟踪microblog
接口入参缺失
root@hj:~/microblog# dfx canister call microblog2 timeline “(1_647_089_465_609_879_000)”
The Replica returned an error: code 4, message: “IC0503: Canister rrkah-fqaaa-aaaaa-aaaaq-cai trapped explicitly: IDL error: too few arguments I”
调用timeline报错,咨询同学得知报错是说接口入参缺失,一下子就意识到了,问题出在那里,因为其他函数调用都没有问题,程序编译也可以通过,但是调用timeline函数却报错,问题在于一开始的canister.post(),是没有输入,调用就会返回数组,现在需要输入参数了,所以需要对canister这个类型的函数定义域值域进行更改。
let canister : Microblog = actor(Principal.toText(id));
//声明一个变量,因为调用的方法posts是async异步的,所以返回的值需要await
//将关注对象的消息列表赋值给msgs
let msgs = await canister.posts(since);