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查询中代表字段,所以在语法解析中做相应的判断,确保原来的语法可以正常工作,没有兼容性问题。
例如,下面的语句是可以正常工作的,没有问题:
提供的方法
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。
- 例子
 
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。
- 例子
 
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一次返回回来,以方便使用。
传递参数
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;
$[finished, value] 这个结构,就可以利用相应的算法。这就是泛型编程(Generic Programming)。