















本文是「far 语言」系列文档之一,总目录见《【far 语言】语言文档目录》。
Far 语法融合了 JS 的灵动、Java 的严谨与 C 的直白。本文面向初识 far 的开发者,用最短篇幅带你读懂它。
class App {
static long main(string args[]){
println("你好,far!");
return 0;
}
}
每个 .far 文件就是一个类,文件名即类名。入口固定为 static long main(string args[]),方法默认返回 0,可不写 return。
string name = "far"; // 字符串
long age = 30; // 64 位整数(默认数值类型)
int score = 100; // 32 位整数注解
double pi = 3.14; // 双精度浮点
bool ok = true; // 布尔
byte b = 0x48; // 8 位整数注解
x := 1; // 短变量声明 :=(自动推断类型,Go 风格)
map<string, string> data = {"name": "far"}; // 字典
object obj = new App(); // 对象 / 自定义类实例
x := 表达式 自动推断。int/short/byte 是编译期宽度注解,运行时统一 64 位。map 键可以是 string 或 long,字面量用 {...},key 可以省略引号:{name: "far", if: 123}。数组采用 C 风格声明,方括号挂在变量名后,字面量用花括号:
int data[3] = [1,2,3]; // 定长数组(数量必须严格相等)
string names[] = ["a","b","c"]; // 未定长(动态)
int m[2][3] = [[1,2,3],[4,5,6]]; // 多维数组
object x[] = [1, 2.1, "3"]; // 混合类型(元素统一 far 对象)
bb := ["4","5"]; // := 推导(元素类型一致)
names.push("d"); // 追加
names.pop(); // 弹出末尾
names[0] = "x"; // 下标读写
println(sizeof(names)); // 长度
class App {
// 静态方法,默认返回 0,可不写 return
static long sum(long a, long b){
return a + b;
}
// 参数默认值(带默认值的参数必须放在最后)
static long greet(string name, long times = 1){
for(long i = 0; i < times; i++){
println("你好," + name);
}
return 0;
}
// 数组参数与返回
static long first(int x[3]){ return x[0]; }
static int[] getList(){ return [1,2,3]; }
static long main(string args[]){
long r = this::sum(3, 4); // 静态方法用 :: 调用
println(r);
this::greet("far"); // 缺省参数
this::greet("far", 3);
return 0;
}
}
f := (x,y)-> println(x + y);,可捕获外部变量。static long test(string type, {string name, long age}){
println(fmt("%s %s %s", type, name, age));
}
// 调用:传 map 或数组都行
this::test("大学生", {"name":"张三", "age":21});
this::test("大学生", {"张三", 21});
T... name(只能放最后),见下节与 function.md。一个 .far 文件内可声明多个类与接口;main 所在类为入口。
interface Named {
string name();
}
class Animal {
long hp = 100;
string speak(){ return "animal"; }
}
// 单继承用冒号;多接口用 impl 逗号列表
class Dog : Animal impl Named {
@Override
string speak(){ return super.speak() + "+woof"; }
string name(){ return "dog"; }
}
class App {
static long main(string args[]){
Named n = new Dog(); // 接口变量 ⇒ 动态分派
println(n.name()); // dog
Animal a = new Dog(); // 向上转型
println(a.speak()); // animal+woof(按运行期类型分派)
return 0;
}
}
impl I1, I2。super.method() 调父类实现;@Override 断言真覆盖,签名写错立刻报错。interface IChild : IParentA, IParentB { }。// if / else
if (a == 1) {
b = 2;
} else if (a == 2) {
b = 3;
} else {
b = 4;
}
// for(初始器 / 条件 / 执行器 都可省略)
for(long i = 0; i < 10; i++){
println(i);
}
// foreach 遍历 map / 数组
foreach(k in data){ println(data[k]); } // k 是 key
foreach(v in arr){ println(v); } // v 是元素
foreach(idx, v in arr){ println(idx); } // idx 是索引
// when 表达式(比 switch 更强,带返回值)
r := when{
a == 2 => "等于2";
a in (1,2,3) => "在集合里";
a in 1..20 => "在区间里";
_ => "默认";
};
// 区间表达式
if (x in 1..10){ println("x 在 1..10"); }
Far 的所有异步任务统一为虚拟线程(vtNew),通信只走 Channel,select 多路等待。
class App {
static long main(string args[]){
// 创建通道对(tx 发送端 / rx 接收端)
map<string, object> ch = chanPair();
map<string, object> tx = ch.tx;
map<string, object> rx = ch.rx;
// 创建并启动虚拟线程(匿名方法闭包,端点由闭包捕获)
map<string, object> t = vtNew((dummy)->{
string msg = chanRecv(rx);
chanSend(tx, "got: " + msg);
}, 0, 0, "worker");
vtStart(t);
// 主协程发送并阻塞接收
chanSend(tx, "hello");
string r = chanRecv(rx);
println(r);
return 0;
}
}
select 多路等待多个 Channel:
select {
case msg = cmd_rx.recv() => {
if (msg == "quit") { break; }
}
case data = data_rx.recv() => { ... }
timeout(100) => { } // 超时分支
}
s := "Hello Far World";
println(s.len()); // 15
println(" AbC ".trim().toLowerCase()); // abc
println("a,b,c".split(",")[1]); // b
println(s.charAt(1)); // e
// 字符串模板
name := "far";
println(`Hello ${name}!`); // Hello far!
import List; // 导入标准库
List<long> nums = new List();
nums.add(1);
nums.add(2);
println(nums.size()); // 2
println(nums.get(1)); // 2
println(nums.toString()); // [1,2]
@Extern("c", "strlen") // 内建:FFI 声明外部 C 函数
static long strlen(RawPtr<AbiChar> s);
@Retention(RUNTIME)
@Target(CLASS, METHOD)
annotation MyAnno {
string name;
}
@Retention(RUNTIME) 可让注解在运行期被反射读取。buf := bytes(64); // 分配 64 字节连续内存
bytesStore<i32>(buf, 0, 42); // 类型化写入
x := bytesLoad<i32>(buf, 0); // 类型化读取
println(x); // 42
try {
throw "出错啦";
} catch (Exception e) {
println(e.getMessage());
} finally {
println("无论是否异常都会执行");
}
完整语法参考:grammar/all.md(由编译器源码核对);并发架构见 concurrency-final.md。
Rust编程语言群 1036955113
java新手自学群 626070845
java/springboot/hadoop/JVM 群 4915800
Hadoop/mongodb(搭建/开发/运维)Q群481975850
GOLang Q1群:6848027
GOLang Q2群:450509103
GOLang Q3群:436173132
GOLang Q4群:141984758
GOLang Q5群:215535604
C/C++/QT群 1414577
单片机嵌入式/电子电路入门群群 306312845
MUD/LIB/交流群 391486684
Electron/koa/Nodejs/express 214737701
大前端群vue/js/ts 165150391
操作系统研发群:15375777
汇编/辅助/破解新手群:755783453
大数据 elasticsearch 群 481975850
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。