跳转至

struct类型

struct类型可以很方便的把相关数据组织在一起,增加代码的可读性和便利性。 struct类型和array数组类型的差别:

  • 没有大小写问题。
  • 写起来更方便。
  • 代码可读性更强。
  • 支持绑定self,相当于可以自由动态定义的class。

语法

除了可以用struct()来构造struct类型外,还提供更方便的$[]语法糖来初始struct。

a := 100;

st := $[
    a : a,
    b : 2,
    c : 3,
    t : array(1,2,3),
    x : $[
        y : 1,
        z : 2   
    ]
];

st 相当于 struct(a:100,b:2,c:3,t:array(1,2,3),x:struct(y:1,z:2))

也可以是$[]:
st := $[];

st 相当于 struct()

函数如何绑定self

方法:把函数的第一个参数定义成self,否则在使用self会报编译错误。struct调用函数的时候,会把自己做为第一个参数传递进去,这样就非常巧妙的解决了self的绑定问题。 例如:

st := $[
  data: "100",
   fun: function (self,x,y,z) begin
      vprintln("=>", x,y,z);
      return self.data;
    end,
  fun2: FindFunction("ClsMethod"),
  (* 如果第一个参数不是self而又使用了self,编译会报错。
  fun3: function (x,y,z) begin
      vprintln("=>", x,y,z);
      return self.data;
    end,
  *)
  // 如果没有使用self可以不定义self。
  fun4: function (x,y,z) begin
      vprintln("=>", x,y,z);
      return "200";
    end,
  // 子结构的self也能绑定到子结构本身。
  child:  $[
    data: "300",
    fun5: function (self,x,y,z) begin
      vprintln("child=>", x,y,z);
      return self.data;
    end
  ]
];

x := st.fun(1,2,3);
vprintln("fun", x);
x := st.fun2(4,5,6);
vprintln("fun2", x);
x := st.fun4(7,8,9);
vprintln("fun4", x);
x := st.child.fun5(8,9,10);
vprintln("fun5", x);

(*
打印:
=> 1 2 3
fun 100
=> 4 5 6
fun2 100
=> 7 8 9
fun4 200
child=> 8 9 10
fun5 300
*)

(* 如果第一个参数不是self而又使用了self,编译会报错。
function NotClsMethod(x,y,z)
begin
    return self.data;
end;
*)

// 这样同样可以工作
function ClsMethod(self,x,y,z)
begin
    vprintln("=>", x,y,z);
    return self.data;
end;    

由于TSL语言中已经用$来做字符串连接,用["字段名"]在select查询中代表字段,所以在语法解析中做相应的判断,确保原来的语法可以正常工作,没有兼容性问题。 例如,下面的语句是可以正常工作的,没有问题:

select "+++"$["a"] from array(('a':'ZZZZZ')) end;

提供的方法

struct()

struct(): 构造struct类型。

  • 参数列表

  • 返回值

struct对象

  • 例子
st := struct();
st.a := 100;
st.b := 2.0;
st.c := "ok";
st.t := array(1,2,3);
st.x := struct();
st.x.y := 1;

struct_attrs

struct_attrs(st): 返回struct类型的所有属性名的列表。

  • 参数列表

    参数 描述
    st struct对象
  • 返回值

字符串数组。

  • 例子
st := struct();
st.a := 100;
st.b := 2.0;
st.c := "ok";
st.t := array(1,2,3);
st.x := struct();
st.x.y := 1;
vprintln(struct_attrs(st));
打印:
array("a","b","c","t","x")

struct_check

struct_check(st): 检查是否struct类型。

  • 参数列表

    参数 描述
    st struct对象
  • 返回值

Bool。

  • 例子
st := struct();
if struct_check(st) then println("ok");

struct_dump

struct_dump(st): 把struct类型的转换成字符串。

  • 参数列表

    参数 描述
    st struct对象
  • 返回值

字符串。

  • 例子
st := struct();
st.a := 100;
st.b := 2.0;
st.c := "ok";
st.t := array(1,2,3);
st.x := struct();
st.x.y := 1;
vprintln(struct_dump(st));
打印:
struct(a:100,b:2.0,c:"ok",t:array(1,2,3),x:struct(y:1))

struct_empty

struct_empty(st): 检查是否struct是否是空,等同于 st = $[]

  • 参数列表

    参数 描述
    st struct对象
  • 返回值

Bool。

  • 例子
st := struct();
if struct_empty(st) then println("ok");

struct_has

struct_has(st, attr): 检查struct类型是否有指定的属性。

  • 参数列表

    参数 描述
    st struct对象
    attr 属性名称
  • 返回值

bool类型。

  • 例子
st := struct();
st.a := 100;

x := struct_has(st, 'a'); // x = True
y := struct_has(st, 'b'); // y = False

struct_get

struct_get(st, attr): 获取struct指定的属性的值。

  • 参数列表

    参数 描述
    st struct对象
    attr 属性名称
  • 返回值

    数组类型,如果发生错误:

    下标
    0 错误代码
    1 错误信息

    没有错误:

    下标
    0 0
    1 返回的数据内容
  • 例子

st := struct();
st.a := 100;

[err, x] := struct_get(st, 'a'); // x = array(0, 'a')
[err, y] := struct_get(st, 'b'); // y = array(-1, 错误信息)

struct_set

struct_set(st, attr, value): 设置struct指定的属性的值。

  • 参数列表

    参数 描述
    st struct对象
    attr 属性名称
    value
  • 返回值

  • 例子

st := struct();
st.a := 100;

struct_set(st, 'b' 101);
[err, x] := struct_get(st, 'b'); // x = array(0, 101)

struct_pack

struct_pack(st): 把struct类型的输出成binary数据,方便保存和传输。

  • 参数列表

    参数 描述
    st struct对象
  • 返回值

binary类型。

  • 例子
st := struct();
st.a := 100;
st.b := 2.0;
st.c := "ok";
st.t := array(1,2,3);
st.x := struct();
st.x.y := 1;
s := struct_pack(st));
st2 := struct_unpack(s);
same := struct_dump(st) = struct_dump(st2); // same = True

struct_unpack

struct_unpack(s): 把struct_pack输出的binary数据再转成struct类型。

  • 参数列表

    参数 描述
    s binary类型
  • 返回值

struct类型。

  • 例子
st := struct();
st.a := 100;
st.b := 2.0;
st.c := "ok";
st.t := array(1,2,3);
st.x := struct();
st.x.y := 1;
s := struct_pack(st));
st2 := struct_unpack(s);
same := struct_dump(st) = struct_dump(st2); // same = True

struct_asarray

struct_asarray(st): 把struct_pack转换成array数组类型。

  • 参数列表

    参数 描述
    st struct对象
  • 返回值

array类型。

  • 例子
st := struct();
st.a := 100;
st.b := 2.0;
st.c := "ok";
st.t := array(1,2,3);
st.x := struct();
st.x.y := 1;
a := struct_asarray(st);
vprintln(a);
打印:
array("a":100,"b":2.0,"c":"ok","t":(1,2,3),"x":("y":1))

struct类型的使用例子

把相关的数据放在一起

例如可以提供rhq_st、md_st或者basic_st等函数,可以把一列数据做为struct一次返回回来,以方便使用。

st := rhq_st();
st.open  表示开盘价
st.high  表示最高价
st.low   表示最低价
st.close 表示收盘价
...

传递参数

struct可以用来传递任意多的参数,使用$[]语法会超级方便,例如:

users := find_user(db, $[ role: 'admin', dept: array('信息部', '交易部') ]);

function find_user(db, cond);
begin
    if struct_has(cond, 'role') then ...
    if struct_has(cond, 'user') then ...
    if struct_has(cond, 'dept') then ...
    ....
end;

相当于类似Python等语言的命名参数的作用,使用它可以帮助设计出更方便、更好用的函数接口。

返回值应用

struct可以很方便返回任意多的结果值。下面是一个很高级的例子:

// 定义fitler算法函数
filter := (self, cond) => $[ 
  iter: self, 
  cond: cond, 
  next: (self) => begin
      while true do begin
        v := self.iter.next();
        if v.finished then return v;
        if self.cond(v.value) then return v;
      end
    end
];

// 定义zip函数
zip := (self, a, b) => 
begin
  st:= $[
     a: a,
     b: b,
    ix: 0,
   len: max(length(a), length(b)),
  next: (self) => begin
      if self.ix >= self.len then
        return $[ finished: true ];
      else
      begin
        value := array(self.a[self.ix], self.b[self.ix]);
        self.ix := self.ix + 1;
        return $[ finished: false, value: value ];
      end
    end,
 ];
 mixin(st, self.algorithm); // 合并算法
 return st;   
end; 

// 组装成iter
iter := $[
  zip: zip,
  algorithm: $[
    filter: filter,
  ]
];

a := array('a', 'b', 'c');
b := array(1,2,3);
for x in iter.zip(a, b).filter((x) => x[0]='a') do
  println("x={}", x);

(*
打印:
x=array("a",1)
*)

function mixin(a, b)
begin
  for attr in array_iter(struct_attrs(b)) do
    if [err, v] := struct_get(b, attr) then
      raise v;
    else
      struct_set(a, attr, v); 
  return a;
end;

function array_iter(a)
begin
  return $[
       a: a,
      ix: 0,
     len: length(a),
    next: (self) => begin
        if self.ix >= self.len then
          return $[ finished: true ];
        else
        begin
          value := self.a[self.ix];
          self.ix++;
          return $[ finished: false, value: value ];
        end
      end
  ]
end;
这个例子用struct和匿名函数实现Iterator。任何数据类型只要按照约定返回 $[finished, value] 这个结构,就可以利用相应的算法。这就是泛型编程(Generic Programming)。