far编程语言 far语言 mud编程语言

far

数据类型

基本数据类型

  • string object number map byte

对象类型(程序员自定义类)

  • object

混合类型

  • var(模糊类型) 包括了基本类型和对象类型

字典

  • map

数字类型

  • number
    包括了整数,小数和大数

数组

数组定义和赋值

number *data = ([1,2,3]);

数组和Js不一样 数组的元素开始符号([ 结束符号])

number *x = ([1,2,3]);

数组可以存储不同的数据类型

var *x = ([1,2.1,"3"]);

上面的元素,编译器会自动生成number number string 类型,如果不想编译器定义元素的类型可以使用转换函数。

var *x = ([ toLong(1),toByte(2),"3" ]);

如果要创建字节数组可以

// 创建有符号字节数组(Byte 范围:-128 ~ 127)
var a = byteArrayOf(0x48, 0x65, 0x6C, 0x6C, 0x6F) ; // 十六进制
var a =  byteArrayOf(72, 101, 108, 108, 111) ;       // 十进

字典 map

字典初始化用({作为开始符号 用})作为结束符号
map data = ({"name":"far"});

表达式

解构表达式

(a,b) = test();//返回值是map或者数组都能结构,并创建a,b两个变量
(a,b) = array;//数组解构,并创建a,b两个变量
(a,b) = ([1,2]);//数组解构,并创建a,b两个变量

元解构表达式

(a,b,c,d) = (test(),([1,2]),"far",1);//自动创建a,b,c,d变量 并依次设置右边的值

元解构表达式返回值

在元解构表达式外层使用() 将强制返回变量a

( (a,b,c,d) = (test(),([1,2]),"far",1) )

这在一些场景下特别有用,可以减少代码。

if(  ( (a,b,c,d) = (test()) ) ){
    //做一些事情
}

当test方法返回的是数组时,可以这样用于判断

Map解构

    var tMap = ({"name":"张三","age":20});
    (name,age) = ({"name":"张三","age":20});

    println(name+" "+age);

输出 张三 20

方法参数解构

  • Map作为解构参数的实参
static number test(string type,{string name,number age}){
    println(fmt("%s %s %s",type,name,age));
}

 static number main(string *args){
   
    var data = ({"name":"赵倩","age":21});
    this::test("大学生",data);
}

  • 数组作为解构参数的实参
static number test(string type,{string name,number age}){
    println(fmt("%s %s %s",type,name,age));
}

 static number main(string *args){
    var data = (["赵倩",21]);
    this::test("大学生",data);
}

方法的参数解构可以实现可变参数的效果

参数解构的默认值
static number test(string type,{string name="far",number ok=123456}){

    println(fmt("%s %s",name,ok));
}

 static number main(string *args){
    var data = ({"name":"张三丰","age":21});
   
    this::test("大学生",({"name":"张三丰","age":21}));
    this::test("大学生",({"name":"张三丰"}));
    this::test("大学生",({}));

三元表达式

var a = x==1 ? 100 : 99;

空值合并表达式

仅仅在左侧操作数为 null 、 undefined、0 时才返回右侧操作数。以后的版本中将会排除0的情况

    var x;
    println(x?:([]));//输出一个空数组

实际用例

    var meTasks =  who.queryTemp("socTasks/"+type);
    meTasks+=({"taskPuber":fileName(this),"task":data[0]});
    who.setTemp("socTasks/"+type,meTasks);

如果第一行meTasks拿到的值是 null|0|undefine 时,下面对meTasks进行+=运算就会报错!需要改成

 var meTasks =  who.queryTemp("socTasks/"+type)?:([]);

区间表达式

用于表示一个数字范围 1..10

in 表达式

检查map中是否存在key

   var a = "name";
   if(  a in ({"name":"张三"}) ){
       println("存在");
  }

检查数字是否在指定的数字集合之内

var a = 2;
if(  a in ([1,2,3]) ){
    println("存在");
}

检查数字是否在指定的范围内

var a = 9;
if(  a in 1..10 ){
    println("存在");
}

when 表达式

代替switch 的表达式,比switch 更强大,更方便!
when表达式具有返回值,每个分支的最后一个表达式作为返回值

  • 必须写默认分支_=>

->左边的表达式 只接受bool表达式的情况,比如

void main(){
    var testWhen = when{
        a==2 => {println("下面的分支不会执行....")};
        a in (1,2,3)=>{"是得,包含了2";};
        a in 1..20 =>println("是得1..20包含了他");
        !a =>println(a);
        _=>"默认分支,这个分支就算不写,编译器也会自动生成,所以when表达式一般默认返回0";
    };
    println(testWhen);
}

when当if使用的情况

  var a = 19;
   when{
    a==2 => {println("下面的分支不会执行....")};
    a in (1,2,3)=>{"是得,包含了2";};
    a in 1..20 =>println("是得1..20包含了他");
    !a =>println(a);
    _=>"默认分支,这个分支就算不写,编译器也会自动生成,所以when表达式一般默认返回0";
 };

when 的作用域

   when{
       a==2 => {
            var bb = 1;
        };
       _=>{ 
            println(bb) 
       };
    }

在上述代码中,bb 变量其作用域仅限于所在的分支块内。在 when 表达式外部或when的其他分支尝试访问 bb 变量会导致编译错误。

语句

import语句

主要作用是将in后面的字符串存入Name,方便在当前文件全局使用

  • 如果括号表达式中的标识符,大于1个时,将以in后面的文件中的export语句导出为准,export只能导出方法
import (Name) in "xxx/xxxx";

return 语句

return 语句后面只能跟表达式或留空

for 语句

基本结构

for(初始器;循环条件表达式;计数器) {代码块}

  • 初始器和计数器支持逗号表达式
for(int a=0,q=1;a<100;i++,c++) {u+user();}
for(;a<1;){}
for(int a=0,q=1;a<100;i++,c++) {u+user();}
for(int x=1;a<1;){}
for(int x=1;;){}
for(int a=0,q=1;a<100;i++){
    for(;a<1;){}
    for(int a=0,q=1;a<100;i++,c++) {u+user();}
    for(int x=1;a<1;){}
    for(int x=1;;){}
}

如果for语句的代码块部分,没有代码,花括号也必须要添加
for 语句代替while语句

for(;bool表达式;){

}

foreach 语句

foreach(ident in ident|expr){ stmt|expr }

  • 遍历map
    var a = ({"name":"far"});
    foreach( k in a){//此处的k 是map得key 会自动创建为局部变量,作用域在foreach内部
        println(a[k]);
    }

输出far

  • 输出数组的每个元素
var a=([1,2,3]);
foreach( k in a){//此处的k是数组中的元素 会自动创建为局部变量,作用域在foreach内部
    println(k);
}

foreach 带 循环编号语法

var a=([1,2,3]);
foreach( idx,k in a){//idx 从0开始,没循环一次递增一次
    println(k);
}

if else

if(a==1){
   aa=2;
}else aa=3;

if(a==1)aa=2;
else aa=3;

if(x==1) o=2;

far的每个文件就是一个类,入口方法为 static number main(string* args){},注意far代码文件的后缀是c,比如
user.c

创建类的实例

使用内置的new方法创建类的实例

var obj = new("obj/user");

类的继承 inherit

inherit "feature/treemap"

方法

far所有的方法默认都返回0,所以,方法内部,写不写return 都可以。

匿名方法

far的匿名方法可以捕获外部变量,如果匿名方法要修改外部的变量,只能是对象类型,基本类型无法修改.

var func = (x,y)-> println(x);

方法参数的默认值

参数带默认值只能排在最后

static number test(string name,number age=20){
    println(age);
}
  • 默认参数值目前只支持string和number 其他类型暂不支持

子类实例调用父类的方法

使用关键字super


super.parentCall();

parentCall 是父类的方法

异常处理

全局异常捕获

先导入类 import (ErrHandler) in "java/com/faros/lib/typeobj/nat/ErrHandler";

再main开始设置全局捕获

ErrHandler::create((thread,err)->{
    println(err);
});


throwAs 抛出异常

throwAs("这是一个异常信息");

静态方法和静态字段

静态字段

static string name;

调用时使用文件名::name
比如当前文件名是A
调用 A::name

静态方法

static number test(){

}

调用方式和调用静态字段一样,静态方法中可以使用this关键字,但调用的是当前类的静态字段或静态方法,且写法为

this::name;
this::setName();

实例方法和实例字段

就是前面不加static ,调用符号换成.,比如

this.name;
this.setName("方东信");

实例方法中调用自己的方法和字段只能用.

多线程

far可以轻松创建千万级线程,不输go语言的协程
thread

 // 创建一个新线程,该线程会进入一个无限循环
    var thread = createThread(()->{
        // 无限循环,线程会一直运行
        for(;;){
            // 注释掉的代码,用于打印线程运行信息
            println("线程运行中");
            // 线程休眠 2000 毫秒
            sleep(2000);
        }
    });
    thread.start();
    //等待线程执行完成
    thread.join();

字符串模版

 void test2(){
    var s="far来了";
    var bb = ()->{
        var bbb = ()->{
            println("${s}");
        };
        bbb();
        
    };
    bb();
}

调用java库

  th.startVirtualThread(() -> {
  var th = JLib("java/lang/Thread");
        println(x);
   });
   th.start();

import java类

import (Os) in "java/com/faros/lib/Os";
import (HttpServer) in "java/com/faros/lib/typeobj/nat/HttpServer";

in 后面的字符串中 第一个斜线/ 前的java表示 导入java的类,如果没有表示导入far的类,导入后,即可使用

任务队列

    import (Task) in "java/com/faros/lib/typeobj/nat/Task";

    static void main(string* args){
        this::taskMgr = Task::create();
        this::taskMgr.submitDelayedTask("aaaa",10000,
            ()->{
                println("IO操作中。。。。");
                return "任务完成,状态返回";
            },
            (e)->{//任务完成调用
                println("程序员: "+e);
            }
        );
    }
   

魔术变量

__DIR__ 获取当前文件所在目录

posted @ 2024-12-05 13:49  方东信  阅读(451)  评论(0)    收藏  举报