精选 Hook 常用指令与核心速查备忘单,涵盖高频用法、配置参数与实用技巧。 Hook 编程语言的单页核心语法速查备忘单。
fn factorial(n) {
if (n == 0)
return 1;
return n * factorial(n - 1);
}
Hook 拥有类似 C 语言风格的现代化简洁语法。
println('Hello, World!');
// Hello, World!
Hook 中的 Hello, World! 入门程序。
cd %tmp%
curl -sSLO https://raw.githubusercontent.com/hook-lang/hook/main/scripts/install.bat
install
这是在 Windows 系统下的安装步骤。
| 类型标识 | 类型标识 |
|---|---|
Nil |
Bool |
Number |
String |
Range |
Array |
Record |
Closure |
基本数据类型列表。
let x = true;
let y = false;
Bool 是布尔类型,其值可以为 true 或 false。
let x = 0;
let degree = 45; // 整数 (integer number)
let pi = 3.14; // 浮点数 (floating-point number)
数字类型可以是整数,也可以是浮点数。
let empty = '';
let name = 'John';
let message = 'Hello, "John"!';
字符串可以使用单引号或双引号包裹。
let range = 1..5;
println(range);
// 1..5
Range 表示一个连续的整数序列。
let fruits = ['apple', 'banana', 'cherry'];
println(fruits);
// ["apple", "banana", "cherry"]
Array 是元素的有序序列。
let p = { x: 5, y: 10 };
println(p);
// {x: 5, y: 10}
Record 将属性映射至对应的具体数值。
let x = nil;
var y;
println(x); // nil
println(y); // nil
nil 表示变量无值或空值。
if (nil) "true" else "false"; // false
if (false) "true" else "false"; // false
if (true) "true" else "false"; // true
if (0) "true" else "false"; // true
if (1) "true" else "false"; // true
if ("") "true" else "false"; // true
if ([]) "true" else "false"; // true
if ({}) "true" else "false"; // true
在 Hook 中只有 nil 和 false 会被评估为假值。
// 这是一个单行注释。
// 这也是
// 多行联排
// 单行注释。;)
Hook 目前仅支持单行注释。
println(1) ; println(2) ; println(3) ;
println(4) ; println(5)
; println(6) ;
; // 报错 error: unexpected token `;`
分号 ; 是必填的,且不允许出现空语句。
{
println('Hello');
{
println('World');
}
}
代码块用于定义作用域。
| 关键字 | 关键字 | 关键字 | 关键字 |
|---|---|---|---|
as |
break |
continue |
do |
else |
false |
fn |
for |
from |
if |
import |
in |
inout |
let |
loop |
match |
nil |
return |
struct |
trait |
true |
var |
while |
Hook 的保留关键字非常精简。
var lowercase;
var CAPS_LOCK;
var camelCase;
var PascalCase;
var snake_case;
var _123;
标识符严格区分大小写。
var x; // x 包含 nil
x = 5; // 现在 x 包含数字
x = 'foo'; // 赋值为字符串
println(x);
数据值拥有类型,但变量本身没有类型约束。
let x = 5;
x = 10; // 报错 error: cannot assign to immutable variable `x`
let y; // 报错 error: unexpected token `;`
不可变变量在声明时必须显式初始化。
let x = 5;
{
let y = 15;
println(x); // 10
println(y); // 15
}
println(x); // 5
println(y); // 报错 error: variable `y` is used but not defined
当堆分配变量超出其作用域时,会被自动释放。
let x = 5;
{
let x = 10; // 遮蔽外层 `x`
println(x); // 10
}
println(x); // 5
局部作用域内的变量可以对同名外层变量进行遮蔽。
println(5 + 10); // 15
println(5 - 10); // -5
println(5 * 10); // 50
println(5 / 10); // 0.5
println(5 % 10); // 5
println(-5); // -5
基础算术运算符。
println(5 == 10); // false
println(5 != 10); // true
println(5 < 10); // true
println(5 > 10); // false
println(5 <= 10); // true
println(5 >= 10); // false
基础比较运算符。
println(true && false); // false
println(true || false); // true
println(!true); // false
基础逻辑运算符。
println(5 & 10); // 0
println(5 | 10); // 15
println(5 ^ 10); // 15
println(~5); // -6
println(5 << 1); // 10
println(5 >> 1); // 2
位运算符与移位运算符。
var x = 5; // 5
x += 10; // 15
x -= 10; // 5
x *= 10; // 50
x /= 10; // 5
x %= 10; // 5
x &= 10; // 0
x |= 10; // 10
x ^= 5; // 15
x <<= 5; // 480
x >>= 5; // 15
x++; // 16
x--; // 15
各种复合赋值运算符。
let x = 5;
let y = if (x > 5) 10 else 20;
println(y);
// 20
在 Hook 中,三元运算符采用 if else 表达式。
let x = 10;
if (x > 5) {
println('x is greater than 5');
}
// x is greater than 5
if 条件分支语句。
let x = 11;
if (x == 5) {
println('x is 5');
} else if (x == 10) {
println('x is 10');
} else {
println('x is neither 5 nor 10');
}
// x is neither 5 nor 10
if else 多重分支语句。
let x = 5;
match (x) {
1 => println("one");
2 => println("two");
3 => println("three");
_ => println("other");
}
// other
match 模式匹配语句。
var x = 0;
while (x < 5) {
print(x);
x += 1;
}
// 01234
while 循环语句。
var x = 0;
do {
print(x);
x += 1;
} while (x < 5);
// 01234
do while 循环语句。
for (var i = 0; i < 5; i++) {
print(i);
}
// 01234
标准的经典 for 循环语句。
loop {
println("Press Ctrl+C to stop");
}
无条件死循环 loop 语句。
var i = 0;
loop {
if (i == 5) break;
print(i);
i += 1;
}
// 01234
使用 break 提前跳出并结束循环。
var i = 0;
loop {
i += 1;
if (i % 2 == 0) continue;
print(i);
if (i == 5) break;
}
// 135
使用 continue 跳过当前循环体剩余代码。
let s = 'Hello';
println(s[0]); // H
println(s[1]); // e
println(s[4]); // o
对字符串进行索引访问将返回长度为 1 的字符子串。
let s = "Hello, World!";
println(s[0..5]); // Hello,
println(s[7..12]); // World!
传入范围 Range 即可对字符串进行切片。
let greeting = 'Hi' + ' there!';
println(greeting);
// Hi there!
使用 + 运算符拼接多个字符串。
let a = [1, 2, 3];
println(a[0]); // 1
println(a[1]); // 2
println(a[2]); // 3
对数组进行索引访问将返回对应的单个元素。
let a = [1, 2, 3, 4];
println(a[0..2]); // [1, 2, 3]
println(a[1..3]); // [2, 3, 4]
println(a[2 .. len(a) - 1]); // [3, 4]
数组索引从 0 开始。
var a = [1, 2];
a[] = 3;
println(a);
// [1, 2, 3]
数组是可变的,使用 [] 在末尾追加元素。
var a = [1, 2, 3];
a[0] = 4;
println(a);
// [4, 2, 3]
更新数组中指定索引处的元素。
let a = [1, 2];
let b = [3];
let c = a + b;
println(c);
// [1, 2, 3]
使用 + 运算符合并拼接数组。
let a = [1, 2, 2, 3];
let b = [2];
let c = a - b;
println(c);
// [1, 3]
计算获取两数组间的差集。
fn sum(a, b) {
return a + b;
}
println(sum(5, 10));
// 15
在 Hook 中函数是一等公民 (First-class citizens)。
fn greet(name) {
println("Hi, " + name + "!");
}
greet("John", "Doe");
// Hi, John!
多余的实参会被自动忽略调整。
let sum = |a, b| {
return a + b;
};
println(sum(5, 10));
// 15
同样支持使用 |a, b| 语法的匿名函数。
let pi = 3.14;
fn area(r) {
return pi * r * r;
}
println(area(5));
// 78.5
Hook 中的闭包仅按值捕获外部变量。
fn apply(f, x) {
return f(x);
}
fn double(x) {
return x * 2;
}
println(apply(double, 5));
// 10
函数可以作为参数传递,也可以作为返回值返回。
fn factorial(n) =>
if (n == 0) 1
else n * factorial(n - 1);
println(factorial(5));
// 120
当函数体为单个表达式时可以使用 => 简写。
fn fib(n) {
if (n < 2)
return n;
return fib(n - 1) + fib(n - 2);
}
println(fib(10));
// 55
原生支持函数的递归调用。
println(type(5));
// number
println('1' + to_string(2));
// 12
println(len('foo'));
// 3
Hook 提供了丰富的内置原生函数。
| 函数名 | 函数名 | 函数名 |
|---|---|---|
print |
println |
type |
is_nil |
is_bool |
to_number |
to_string |
hex |
len |
exit |
assert |
panic |
struct Point {
x, y
}
let p = Point { 5, 10 };
println(p);
// {x: 5, y: 10}
结构体 (Struct) 是记录 (Record) 的原型模版。
println(p.x); // 5
println(p.y); // 10
使用点号 . 访问 Record 中的字段属性。
p.x = 10;
p.y = 20;
println(p);
// {x: 10, y: 20}
更新修改 Record 中字段的值。
let a = [1, 2];
let [x, y] = a;
println(x); // 1
println(y); // 2
直接对数组元素进行解构并声明变量。
let p = { x: 5, y: 10 };
let { x } = p;
println(x);
// 5
使用 {} 解构 Record 字段。
let a = [1, 2];
let [x] = a;
let [_, y] = a;
println(x); // 1
println(y); // 2
使用 _ 下划线跳过开头的元素。
import math;
println(math.sqrt(25));
// 5
使用 import 将模块引入当前作用域。
// my_module.hk
fn useful_fn() {
return "Nothing";
}
return { useful: useful_fn };
返回一个包含要导出符号的 Record 记录。
import "./my_module.hk" as my;
println(my.useful());
// Nothing
指定本地模块文件的相对路径。
import { pow, sqrt } from math;
let [ b, c ] = [ 4, 3 ];
let a = sqrt(pow(b, 2) + pow(c, 2));
println(a);
// 5
使用 {} 挑选导入指定的模块符号。
| 模块名 | 模块名 | 模块名 | 模块名 |
|---|---|---|---|
math |
os |
io |
numbers |
strings |
arrays |
utf8 |
hashing |
encoding |
socket |
json |
lists |
详情请参阅:Core Modules 核心模块文档
| 模块名 | 模块名 | 模块名 | 模块名 |
|---|---|---|---|
bigint |
crypto |
curl |
fastcgi |
geohash |
leveldb |
mysql |
redis |
regex |
sqlite |
uuid |
zeromq |
扩展模块列表。
import { stderr, writeln } from io;
writeln(stderr, "Something went wrong");
// Something went wrong
使用 io 模块向 stderr 标准错误流输出。
import hashing as h;
let d = h.sha256('Hello, world!');
println(hex(d));
// 315f5bdb76d078c43b8ac0064e4a...
hashing 模块提供常用的加密哈希函数。
import json;
let j = '{"x": 1, "y": 2}';
let p = json.decode(j);
println(p.x); // 1
let k = json.encode(p);
println(type(k)); // string
使用 json 模块解析和生成 JSON 文本。
println(to_int('foo'));
// 运行时错误: runtime error: type error: argument #1 is not a convertible string
// at to_int() in <native>
// at main() in example.hk:1
Hook 使用 Panic 恐慌模式处理错误,发生错误时解释器会立即终止。
println('Hello, World!');
// 语法错误: syntax error: unexpected end of file
// at main() in example.hk:1,25
Hook 拥有严格的语法解析逻辑。
panic('Something went wrong');
// panic: Something went wrong
// at main() in example.hk:1
使用内置函数 panic 抛出并报告异常错误。
assert(5 > 10, '5 is not greater than 10');
// assert: 5 is not greater than 10
// at main() in example.hk:1
使用内置函数 assert 断言检查条件。
fn divide(a, b) {
if (b == 0)
return [nil, "division by zero"];
return a / b;
}
if (let [ok, err] = divide(5, 0); ok) {
println(ok);
} else {
println(err);
}
// division by zero
使用元组对同时返回计算结果与错误消息。
if (let [ok, err] = divide(5, 0); err) {
return [nil, err];
}
直接向上传递错误而不进行处理。