@符号

在Z1h中, @符号有丰富的作用, 且完全不同于其他主流语言的@已知用法. 如果应用得当, 可以大大简化代码, 提高开发效率. 以及可以起到很多特殊的效果, 例如异常处理、断点debug等等.

便捷函数

先上一段示例代码: // 声明一个便捷函数 z1h.at(e=>{ print('左值为:', e) }); print('结果为:', 100@ + 123@) // 输出结果如下 // 左值为: 100 // 左值为: 123 // 结果为: 223 可以看到, 通过调用z1h.at, 将一个函数设为便捷函数之后, 就可以使用@符号了. 简单地说, @符号的作用就是: 调用便捷函数, 并将左值作为参数传入 特性如下: 1. 结合优先级最高, 即1/0@实质上等价于1/(0@), 而(1/0)@ 2. 即使@的左值抛出异常, 也仍然会执行便捷函数 3. 默认情况下, 便捷函数的运行结果不会影响函数调用处的值, 但是运行过程抛出的异常会传递 4. 可以声明带别名的便捷函数, 并且别名的任意前缀均可触发该便捷函数 5. 便捷函数的作用域为当前代码块, 通过指定参数也可以声明到全局作用域 接下来分点介绍:

特性1, 结合优先级

运行代码 // 声明一个别名为foo的便捷函数 z1h.at("foo", e => { print("foo:", e) }); // 通过 xxx@f / xxx@fo / xxx@foo 均可运行别名为foo的便捷函数 2 * 200 @f; // 200 (2 * 200)@f; // 400 2 * (200@f); // 200 可知, @符号的优先是最高的

特性2, 可以处理异常

示例代码: // 便捷函数有3个参数, 分别是: [左值, 异常, 上下文] z1h.at((val, err, ctx) => { if (err) { print('抛出了异常 %v, 代码为 %s'.fmt(err, ctx.code)) } else { print('顺利执行, 左值为 %v, 代码为 %s'.fmt(val, ctx.code)) } }); (100 / 20) @ // 顺利执行, 左值为 5, 代码为 100 / 20 (100 / 0) @ // 抛出了异常 .... division by zero, 代码为 100 / 0 上下文是一个包含了很多特殊函数的对象, 例如可以将抛出的异常捕获、设置返回值、获取运行的代码、延时执行等等 z1h.at((val, err, ctx) => { var e = ctx.recover() // 捕获并销毁异常 if (e) { print('捕获了异常:', e.Error()) ctx.result(1000) // 有异常的情况下, 设置返回值为1000 } else { print('顺利执行') } }); print('结果为:', (100/20)@ + (100/0)@) // 结果为: 1005

特性3, 返回值

便捷函数无论return了什么值, 都不会取代调用处的原值, 但是如果调用上下文对象的result函数, 即可设置返回值 z1h.at('foo', e => { return 100 // 这种方式不会修改到值 }); z1h.at('bar', (_, _, ctx) => { ctx.result(200) // 设置返回值 }); var a = 500@f; // foo函数 var b = 600@b; // bar函数 print({a, b}) // {"a":500,"b":200}

特性4, 别名

上文特性1中已经演示了便捷函数的别名用法, 在调用z1h.at的时候, 如果第一个参数是字符串, 就可以为该便捷函数设置别名, 例如 z1h.at("helloworld", e => print('Hello,', e)) 那么接下来就可以用 值@helloworld 的方式来调用便捷函数了 并且可以使用任意前缀调用, 例如 值@hello 甚至 值@h 123@hello 1@h 注意, 如果别名前缀有重复的, 会起到覆盖的作用, 例如: z1h.at("helloworld", e => print('Hello,', e)); z1h.at("hi", e => print('Hi,', e)); 1@h // 调用的是后声明的hi 1@he // 调用的是helloworld 1@hi // 调用的是吻合前缀的hi

特性5, 作用域

运行以下代码 z1h.at("hi", e => print('Hi outside,', e)); 111@h; { z1h.at("hi", e => print('Hi inside,', e)); 222@h; } 333@h; 你将会看到输出为: Hi outside, 111 Hi inside, 222 Hi outside, 333 也就是inside的便捷函数不会影响到代码块之外的333 如果想要指定一个全局作用域的便捷函数, 将z1h.at的最后一个参数设为1即可 // 如果在这里声明wow, 优先级高于全局作用域, 会干扰理解 { z1h.at("wow", e => print('Wow inside,', e), 1); 111@w; } 222@w; 输出: Wow inside, 111 Wow inside, 222 此时, 代码块之外的222也被影响了

内置便捷函数

z1h的运行时内置了几个便捷函数, @ = assert; @s = string; @t = time 示例代码: $db.find('test')@ // 等同于assert($db.find('test')) 123@s + 456 // 输出123456而非579, 因为@s将左值转为了字符串类型 "20210119"@t // 输出了一个Time对象 // 结合以上, 在数据库中查找2021年之前过期的会员用户数 $db.count('user', { vip: {$lt: 2020@[email protected]()} })@