Fun 语言手册
0. Fun 语言简介
Fun 是一种易学易用的支持面向对象和函数式特性的结构化命令式编程语言.
Fun 的语法非常简单清晰, 主要语法来自 Ada 语言, 为了简洁, 适当的做了一些改变. 语法主要从以下几个方面着重考虑, 多用英文关键字(虽然实际上也支持中文关键字, 但不提倡用中文编程. Fun 选用的关键字都是优先考虑最常用的, 即使英文基础不高, 也完全不是问题), 少用符号, 易读易写易修改. Fun 是纯粹的块结构语言, 除了命令, 其他全部是块结构(甚至取消了一行 if 的用法). 块之间任意嵌套, 不做限制, 也就是你可以在 if 里面声明函数或者类, 任意的. Fun 支持常见的控制结构. Fun 支持异常处理, 用法比较像 Delphi, 只不过同时支持 "except" 和 "finally". Fun 是一种动态类型语言, 类型无需声明, 类型之间在需要的时候自动转换, 当然 Fun 也提供了显式转换功能. Fun 支持基于类的单继承面向对象功能, 支持少量的运算符重载. Fun 支持函数式用法, 用法跟 Lisp 和 Javascript 差不多. Fun 实现了一个非常简单高效的垃圾回收器, 程序员无需关心内存释放问题. Fun 支持 Perl 兼容的正则表达式, 处理文本非常方便. Fun 的基础结构是一种类似于 Lisp 的表, 用来支持各种数据结构, 如数组, 字典等.
1. 控制结构
Fun 选用类 Ada 语言的控制结构语法. 用过 Ada 语言的人就会知道, Ada 式语法非常简单清晰, 易读, 易于输入, 易于修改. Ada 语言算是 Pascal 语言的进化版, 比如去掉了 Pascal 里面不合理的分号分隔用法, 改为分号结束(初学 Pascal 的人几乎一定会在这个地方载跟头, 就像初学 C 的人也几乎一定会在 = 和 == 这个地方载跟头一样). Fun 修改了少数几个地方, 目的也是为了更清晰易读易输入, 比如将 "when ... =>" 改为 "when ... do", 增加了 "while ... do" 和 "for ... do", 等.
Fun 的异常处理主要来自于 Delphi, 做了些增强, 让 "except" 和 "finally" 可以同时用. 因为是动态类型, 所以去掉了 "on", 如果程序员需要判断处理, 可以用 "case" 替代.
1.1 分支结构: if/case
包括 "if..then" 和 "case..when".
1.1.1 if
- ########################################
- # if
- ########################################
- # if expression then cmds
- # { elsif expression then cmds } 0..n
- # [ else cmds ] 0..1
- # end if;
- ########################################
-
- if true then
- ..?. true; # HIT
- end if;
-
- if false then
- ..?. false;
- else
- ..?. true; # HIT
- end if;
-
- if false then
- ..?. false;
- elsif true then
- ..?. true; # HIT
- else
- ..?. "What's wrong with you?";
- end if;
-
- ########################################
- # 1. Comments start with "#" or "//"
- # Comment block: #* ... #
- # 2. "true", "false" are keywords
- # 3. "?." means output (append extra \r\n)
- # "?," means output (append a blank' ')
- # "?:" means output (append a TAB )
- # "?" means output (without any extra)
- ########################################
True
True
True
下载该演示
1.1.2 case
- ########################################
- # case
- ########################################
- # case expression is
- # { when value do cmds }+ 1..n
- # [ else cmds ] 0..1
- # end case;
- ########################################
-
- var exp = 1;
-
- case exp is
- ..when 1 do
- ....?. 1; # HIT
- ..when 2 do
- ....?. 2;
- ..when 3 do
- ....?. 3;
- ..else
- ....?. 'else';
- end case;
-
- exp = "Hello";
-
- case exp is
- ..when "Good" do
- ....?. @ & ' morning!';
- ..when "Bad" do
- ....?. @ & ' command or file name!';
- ..when "Hello" do
- ....?. @ & ', world!'; # HIT
- ..else
- ....?. @ & ' not found!';
- end case;
-
- ########################################
- # 1. Value in "when" may be anything ([...] or /.../)
- # 2. "@" is a built-in variable in "case"
- # @ <- expression in "case ... is"
- # 3. "&" means string concat
- # 4. String quoted with ' or " or `
- ########################################
1
Hello, world!
下载该演示
1.2 循环结构: loop
- ########################################
- # loop
- ########################################
- # loop
- # cmds
- # end loop;
- ########################################
-
- var i = 1;
-
- loop
- ..?. i;
- ..exit;
- end loop;
-
- loop
- ..exit when i > 9;
- ..? i;
- ..i += 1;
- end loop;
- ?. '..DONE';
-
- i = 9;
-
- loop
- ..i -= 1;
- ..exit when i <= 0;
- ..next when i mod 2 = 1;
- ..? i;
- end loop;
- ?. '..DONE';
-
- ########################################
- # 1. "exit" means exit the loop
- # "exit when" means when ... exit ...
- # "next" means skip to next loop
- # "next when" means when ... next ...
- # 2. v += ... means v = v + ...
- # v -= ... means v = v - ...
- # v *= ... means v = v * ...
- # v &= ... means v = v & ...
- ########################################
1
123456789..DONE
8642..DONE
下载该演示
1.2.1 while
- ########################################
- # loop-while
- ########################################
- # while expression loop
- # cmds
- # end loop;
- ########################################
-
- var i = 1;
-
- while i <= 9 loop
- ..? i;
- ..i += 1;
- end loop;
- ?. '..DONE';
-
- i = 9;
-
- while i > 0 do
- ..? i;
- ..i -= 1;
- end do;
- ?. '..DONE';
-
- ########################################
- # 1. while ... "loop" -> while ... "do"
- # end "loop" -> end "do"
- ########################################
123456789..DONE
987654321..DONE
下载该演示
1.2.2 for
- ########################################
- # loop-for
- ########################################
- # for v = e1 to e2 [step e3] loop
- # cmds
- # end loop;
- ########################################
-
- for i = 1 to 9 loop
- ..? i;
- end loop;
- ?. '..DONE';
-
- for i = 9 to 1 step -1 do
- ..? i;
- end do;
- ?. '..DONE';
-
- ########################################
- # 1. for ... "loop" -> for ... "do"
- # end "loop" -> end "do"
- # 2. v is a built-in variable in loop
- ########################################
123456789..DONE
987654321..DONE
下载该演示
1.2.3 for-in
- ########################################
- # loop-for-in
- ########################################
- # for v in expression loop
- # cmds
- # end loop;
- ########################################
- # for k : v in expression loop
- # cmds
- # end loop;
- ########################################
- # for k : v, i in expression loop
- # cmds
- # end loop;
- ########################################
- # for v, i in expression loop
- # cmds
- # end loop;
- ########################################
-
- for i in [1, 2, 3, 4, 5] loop
- ..? i;
- end loop;
- ?. '..DONE';
-
- for i in [5, 4, 3, 2, 1] do
- ..? i;
- end do;
- ?. '..DONE';
-
- for k: i in [a: 1, b: 2, c: 3] do
- ..?, k;
- ..?, i;
- end do;
- ?. 'DONE';
-
- for k: i, j in [a: 1, b: 2, c: 3] do
- ..?, k;
- ..?, i;
- ..?, j;
- end do;
- ?. 'DONE';
12345..DONE
54321..DONE
a 1 b 2 c 3 DONE
a 1 0 b 2 1 c 3 2 DONE
下载该演示
1.3 异常结构: try
- ########################################
- # try
- ########################################
- # try cmds
- # [ except cmds ] 0..1
- # [ finally cmds ] 0..1
- # end try;
- ########################################
-
- try
- ..? 'try..'; # HIT
- except
- ..? 'except..';
- end try;
- ?. 'DONE';
-
- try
- ..? 'try..'; # HIT
- finally
- ..? 'finally..'; # HIT
- end try;
- ?. 'DONE';
-
- try
- ..? 'try..'; # HIT
- except
- ..? 'except..';
- finally
- ..? 'finally..'; # HIT
- end try;
- ?. 'DONE';
-
- try
- ..? 'try..'; # HIT
- ..? 1 / 0;
- ..? '1 / 0';
- except
- ..? 'except..'; # HIT
- ..? @ & '..'; # HIT
- finally
- ..? 'finally..'; # HIT
- end try;
- ?. 'DONE';
-
- try
- ..? 'try..'; # HIT
- ..raise "Stop!";
- ..? 'Stop!';
- except
- ..? 'except..'; # HIT
- ..? @ & '..'; # HIT
- finally
- ..? 'finally..'; # HIT
- end try;
- ?. 'DONE';
-
- ########################################
- # 1. "@" is a built-in variable in "except"
- # @ <- exception
- # 2. "raise" can throw an exception
- # exception can be anything
- ########################################
try..DONE
try..finally..DONE
try..finally..DONE
try..except..Floating point division by zero..finally..DONE
try..except..Stop!..finally..DONE
下载该演示
2. 变量: 命令式语言的精髓
Fun 是一种命令式语言, 变量算是一种核心概念, 程序通过修改变量的值来修改程序的执行状态(纯函数式语言则不同, 完全无需变量, 程序流程相当于一连串函数串联起来). Fun 语言的变量是动态类型的(不是无类型), 声明时无需声明类型, 类型取决于变量的值, 同一个变量取不同的值, 其类型也不同. 变量在不同的地方使用, 需要做类型转换时会自动转换, 程序员也可自行转换. Fun 的变量值修改, 只能在单一语句中完成(也叫做命令), Fun 不支持类 C 的 ++/-- 或者表达式中的 = 赋值功能.
2.1 命名
Fun 语言支持如下的字母表, 用来为变量(包括函数, 类等)命名: /[$_@A-Za-z][$_@A-Za-z0-9]*/ (正则表达式). 实际上, 也包括中文.
关键字(40 个, 全部保留, 程序员不能拿关键字来命名):
if then elsif else end case is when do
loop exit next while for to step in
try except finally raise fun return
class atom new var use as null nil
div mod not and or xor bit true false
Fun 语言里面还有 4 个内置变量:
@ result this base
@ 用在:
"case", "except", "fun"
result 用在:
"fun"
this/base 用在
"class"
2.2 类型
Fun 语言的变量有如下数据类型: 基本型(数字, 字符串, 布尔, 时间), 对象型(列表, 对象, 类, 函数), 还有其他的.
所有的基本型都是值类型. 所有的对象型都是引用类型, 赋值时仅仅 shallow copy (当然了, 可以使用内置的 '@clone' 函数来复制对象).
- ########################################
- # type
- ########################################
- # Number: [0-9]+(\.[0-9]+)?(e-?[0-9]+)?|0x[0-9a-f]+|0b[01]+
- # String: Quoted with ' or " or `
- # Time: @String
- # Bool: true/false
- # Null: null/nil
- ########################################
-
- # Number
- ?. 123456789;
- var n = 1.23456789; ?. n;
- n = 0xffffffff; ?. n;
-
- # String
- ?. "This is a string.";
- var s = 'Hello, string.'; ?. s;
- ?. 'it''s me'; // '...''...', "...""...", `...``...`, `...`id`...` (for quine)
-
- # Time
- ?. @"2010-04-09 15:35:15";
- var t = @'2010-04-09 15:35:15'; ?. t;
-
- # Bool
- ?. true;
- var b = false; ?. b;
-
- # Null
- ?. '[' & null & ']';
123456789
1.23456789
4294967295
This is a string.
Hello, string.
it's me
2010-4-9 15:35:15
2010-4-9 15:35:15
True
False
[]
下载该演示
2.3 运算
变量运算组成表达式, Fun 有以下类型的运算以及表达式: 数字运算, 字符串运算, 布尔运算等. 布尔表达式经常用在控制结构的条件部分.
- ########################################
- # calc
- ########################################
- # Number: + - * / div mod ^
- # Bits: << >> (bit not/and/or/xor)
- # String: &
- # Time: + -
- # Bool: not and or xor
- # Regex: =~ !~
- # Set: in
- # Others: = !=(<>) < <= > >=
- # Set/Others for any types
- ########################################
- # precedence (default left association)
- ########################################
- # () [] .
- # ^
- # * / div mod
- # (bit not) -> right
- # (bit and/or/xor) << >>
- # + -
- # &
- # = != <> < <= > >= in =~ !~ -> none
- # not -> right
- # and
- # or xor
- ########################################
- # short-circuit calculation
- ########################################
- # and
- # or
- ########################################
-
- # Number
- var n1 = 9;
- var n2 = 3.3;
- ?. n1 + n2;
- ?. n1 - n2;
- ?. n1 * n2;
- ?. n1 / n2;
- ?. n1 div "4"; # Type conversions automatically
- ?. n1 mod '4'; # Type conversions automatically
- ?. n1 ^ 3; # power
-
- # Bits
- n1 = 0x0f;
- n2 = 0xf0;
- ?. n1 << 4; # shift left
- ?. n2 >> 4; # shift right
- ?. bit not n1;
- ?. n1 bit and n2;
- ?. n1 bit or n2;
- ?. n1 bit xor n2;
-
- # String
- var s1 = 'Hello';
- var s2 = ", world!";
- ?. s1 & s2 & ' - ' & 10000; # Type conversions automatically
-
- # Time
- var t1 = @"2010-04-09 15:35:15";
- var t2 = @'2010-03-09 15:35:15';
- ?. t1 + 100;
- ?. t1 - t2;
-
- # Bool
- var b1 = true;
- var b2 = false;
- ?. not not b1;
- ?. not (b1 and b2);
- ?. b1 or b2;
- ?. b1 xor b2;
-
- # Set
- ?. "Hello" in ["Hello", "World"];
-
- # Others - Compare
- ?. not 1 = 2;
- ?. 1 != 2;
- ?. 1 <> 2;
- ?. 1 < 2;
- ?. 1 <= 2;
- ?. not 1 > 2;
- ?. not 1 >= 2;
-
- # Null - All null values equal null (number, string, bool, etc.)
- ?. null = 0;
- ?. null = false;
- ?. null = '';
-
- # Short-circuit calculation
- ?. true or 1 = 0; # "1 = 0" doesn't need calc
- ?. false and 1 = 1; # "1 = 1" doesn't need calc
-
- # Optional
- ?. Undefined?;
- ?. Undefined?.Undefined?;
12.3
5.7
29.7
2.72727272727273
2
1
729
240
15
4294967280
0
255
255
Hello, world! - 10000
2010-7-18 15:35:15
31
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
False
下载该演示
2.4 赋值
变量值只能在一条命令语句中修改, 表达式中是不能修改变量值的.
- ########################################
- # assign
- ########################################
- # v = expression;
- # v += expression;
- # v -= expression;
- # v *= expression;
- # v &= expression;
- ########################################
-
- var a = 1; ?. a = 1;
- a += 2; ?. a = 3;
- a -= 1; ?. a = 2;
- a *= 2; ?. a = 4;
- a &= 5; ?. a = '45';
True
True
True
True
True
下载该演示
2.5 作用域
变量在块中以关键字 "var" 来声明. 一个模块(文件)或者任意控制结构如 if/elsif/else/case/when/loop 都是块, fun/class 也是块. 变量的作用域规则非常简单, 靠近自己的块就是它的作用域, 即使声明在当前语句的后面也是如此(因此, Fun 语言无需提前声明).
- ########################################
- # scope
- ########################################
-
- var a = 1;
- var b = 2;
- ?. a = 1;
- ?. b = 2;
-
- if true then
- ..var a = 2; # new "a"
- ..b = 22; # old "b"
- ..?. a = 2;
- ..?. b = 22;
-
- ..if true then
- ....var a = 3; # new "a"
- ....b = 33; # old "b"
- ....?. a = 3;
- ....?. b = 33;
- ..end if;
-
- ..?. a = 2;
- ..?. b = 33;
- end if;
-
- ?. a = 1;
- ?. b = 33;
True
True
True
True
True
True
True
True
True
True
下载该演示
3. 函数: 基本的过程化模块化编程
Fun 是一种过程化语言, 支持传统的模块化编程. 函数可以定义在任何块结构中, 其作用域与变量作用域完全相同(实际上, 函数名跟变量完全等价, 在函数式编程的介绍里面会看到).
3.1 函数声明与调用
- ########################################
- # fun
- ########################################
- # fun name ( parameters )
- # cmds
- # end fun;
- ########################################
-
- # Define a function named "foo"
- fun foo()
- ..?. 'Hello, fun!';
- end fun;
-
- # Call function "foo"
- foo();
-
- # Define a function with parameters
- fun max(a, b)
- ..if a > b then
- ....result = a;
- ..else
- ....result = b;
- ..end if;
- end fun;
-
- fun min(a, b)
- ..if a < b then
- ....return a;
- ..else
- ....return b;
- ..end if;
- end fun;
-
- ?. max(1, 9);
- ?. max(9, 1);
- ?. min(1, 9);
- ?. min(9, 1);
-
- ########################################
- # 1. "result", "@" are built-in variables in "fun"
- # they all be defined as the result value of the fun
- # 2. "return" means return the fun
- # it can return with/without a value
- # 3. "exit" can exit a fun too
- ########################################
Hello, fun!
9
9
1
1
下载该演示
3.2 默认参数
- ########################################
- # fun-default
- ########################################
-
- # test define
- fun test(a, b, c)
- ..# embed inner fun
- ..fun echo(name, str)
- ....? name & '=[' & str & '] ';
- ..end fun;
-
- ..# echo the parameters
- ..echo('a', a);
- ..echo('b', b);
- ..echo('c', c);
- ..?. 'DONE';
- end fun;
-
- test(1, 2, 3);
- test(1, 2); # keep param(s) 'c' as null
- test(1); # keep param(s) 'b' and 'c' as null
-
- ########################################
- # 1. Default arguments always be set as null
- ########################################
a=[1] b=[2] c=[3] DONE
a=[1] b=[2] c=[] DONE
a=[1] b=[] c=[] DONE
下载该演示
3.3 命名参数
- ########################################
- # fun-named
- ########################################
- # { name: value } 0..n
- ########################################
-
- # test define
- fun test(a, b, c)
- ..# embed inner fun
- ..fun echo(name, str)
- ....? name & '=[' & str & '] ';
- ..end fun;
-
- ..# echo the parameters
- ..echo('a', a);
- ..echo('b', b);
- ..echo('c', c);
- ..?. 'DONE';
- end fun;
-
- test(a: 1, b: 2, c: 3);
- test(c: 1, b: 2, a: 3);
- test(c: 1, b: 2); # keep param(s) 'a' as null
- test(c: 1); # keep param(s) 'b' and 'a' as null
-
- ########################################
- # 1. Default arguments always be set as null
- ########################################
a=[1] b=[2] c=[3] DONE
a=[3] b=[2] c=[1] DONE
a=[] b=[2] c=[1] DONE
a=[] b=[] c=[1] DONE
下载该演示
3.4 传值与传址
Fun 的函数调用参数支持 2 种类型, 即传值和引用, 默认是传值. 如果需要传递引用, 则必须在调用时给参数加上 "var" 关键字, 这样被调用函数里面可以直接修改该参数的值.
值得注意的是, 所有的对象型变量, 在赋值以及传参数时, 直接就是传的指针(地址), 但如果不加 "var" 关键字, 则传递方的变量不被被调用函数修改.
- ########################################
- # fun-ref
- ########################################
-
- fun swap(a, b)
- ..var t = a;
- ..a = b;
- ..b = t;
- end fun;
-
- var i = 1;
- var j = 9;
- ?. i & ' ' & j;
-
- swap(i, j); # Call by value
- ?. i & ' ' & j;
-
- swap(var i, var j); # Call by reference
- ?. i & ' ' & j;
-
- swap(var i, var j); # Call by reference
- ?. i & ' ' & j;
-
- ########################################
- # 1. pass "var" arguments to call by reference
- ########################################
1 9
1 9
9 1
1 9
下载该演示
3.5 递归调用
- ########################################
- # fun-recursion
- ########################################
-
- for i = 1 to 17 do
- ..?. fact(i);
-
- ..fun fact(n)
- ....if n > 1 then
- ......result = n * fact(n - 1); # call fact recursion
- ....else
- ......result = 1;
- ....end if;
- ..end fun;
- end do;
1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
6227020800
87178291200
1307674368000
20922789888000
355687428096000
下载该演示
3.6 模块引用
Fun 支持模块复用, 用 "use" 来引用其他模块, 引用时可以重命名.
- ########################################
- # use
- ########################################
- # use string;
- ########################################
- # use string as id;
- ########################################
-
- ?. '----Use fun-ref.fun ...';
-
- use 'fun-ref.fun';
-
- ?. '----Used----';
-
- i = 11;
- j = 99;
- ?. i & ' ' & j;
-
- swap(i, j); # Call by value
- ?. i & ' ' & j;
-
- swap(var i, var j); # Call by reference
- ?. i & ' ' & j;
-
- swap(var i, var j); # Call by reference
- ?. i & ' ' & j;
-
- use 'fun-ref.fun' as lib; # use as alias
-
- i = 111;
- j = 999;
- ?. i & ' ' & j;
-
- lib.swap(var i, var j); # use via module_alias.name
- ?. i & ' ' & j;
-
- ########################################
- # 1. The used file will be inited at first (Run Once)
- # 2. Can access the IDs for top level of the used file
- # Variables and functions/classes and so on
- # 3. The latest IDs are valid for same name
- # Multiple files be used
- # 4. Can re-name the module as a new id, such as
- # use "..." as newone;
- # ?. newone.test();
- # 5. Files Can be used in anywhere
- ########################################
----Use fun-ref.fun ...
1 9
1 9
9 1
1 9
----Used----
11 99
11 99
99 11
11 99
111 999
999 111
下载该演示
4. 类: 基于类的面向对象编程
Fun 是一种面向对象编程语言, 支持基于类的单继承和多态特性. 支持有限的运算符重载.
4.1 类声明与对象创建
Fun 使用 "class" 关键字来定义类, 类可以定义在任何地方. 类实例即对象的创建时会调用类的构造函数, 也就是类体里面的代码(不包括成员函数里面的代码).
- ########################################
- # class
- ########################################
- # class name ( parameters )
- # cmds
- # end class;
- ########################################
-
- # define a class
- class CA()
- ..# test for class constructor
- ..? 'CA-constructor-starting..';
-
- ..# member variable
- ..var name = 'CA';
-
- ..# member function
- ..fun showName()
- ....?. name;
- ..end fun;
-
- ..fun getName()
- ....return name;
- ..end fun;
-
- ..?. 'DONE';
- end class;
-
- # create a class instance (object)
- var a = CA();
-
- # use the member variable of object
- ?. a.name;
-
- # use the member function of object
- a.showName();
- ?. a.getName();
CA-constructor-starting..DONE
CA
CA
CA
下载该演示
4.2 继承与多态
Fun 语言只支持单继承. 当一个对象被创建时, 构造函数按照从基类到子类的顺序自动调用. 所有同名成员会自动重载覆盖基类的同名成员. 但程序员可以有选择的使用重载或是当前成员, 凡用 this 前缀调用的成员, 一律是重载, 其他是当前成员.
- ########################################
- # class-subclass
- ########################################
- # class name = base ( parameters )
- # cmds
- # end class;
- ########################################
-
- # define a class
- class CA()
- ..? 'CA-constructor-starting..';
-
- ..var name = 'CA';
-
- ..fun showName()
- ....?. name;
- ..end fun;
-
- ..fun getName()
- ....return name;
- ..end fun;
-
- ..?. 'DONE';
- end class;
-
- # define a sub-class
- class CB = CA()
- ..? 'CB-constructor-starting..';
-
- ..name = 'CB';
-
- ..?. 'DONE';
- end class;
-
- class CC = CB()
- ..? 'CC-constructor-starting..';
-
- ..name = 'CC';
-
- ..fun showName()
- ....?. '--CC.showName() .. ' & name & ' .. DONE';
- ..end fun;
-
- ..?. 'DONE';
- end class;
-
- fun test(o)
- ..?. o.name;
- ..o.showName();
- ..?. o.getName();
- end fun;
-
- ?. '--CA--';
- test( CA() );
-
- ?. '--CB--';
- test( CB() );
-
- ?. '--CC--';
- test( CC() );
--CA--
CA-constructor-starting..DONE
CA
CA
CA
--CB--
CA-constructor-starting..DONE
CB-constructor-starting..DONE
CB
CB
CB
--CC--
CA-constructor-starting..DONE
CB-constructor-starting..DONE
CC-constructor-starting..DONE
CC
--CC.showName() .. CC .. DONE
CC
下载该演示
4.3 This and base
- ########################################
- # class-base
- ########################################
- # class name = base ( parameters )
- # cmds
- # end class;
- ########################################
- # this.field or this.method()
- # base.field or base.method()
- ########################################
-
- // base class
- class CBas()
- ..var field = 'field';
-
- ..fun method()
- ....?. field;
- ..end fun;
-
- ..fun test()
- ....?. field;
- ....?. this.field;
- ....method(); // call the method in this class
- ....this.method(); // call the override method
- ..end fun;
- end class;
-
- // sub class
- class CSub = CBas()
- ..fun method()
- ....? 'CSub.method()..';
- ....base.method(); // call the method in base classes
- ..end fun;
- end class;
-
- // test ...
- var bas = CBas();
- var sub = CSub();
- ?. '--test--bas--'; ?. bas.field; bas.test();
- ?. '--test--sub--'; ?. sub.field; sub.test();
- // test ...
- bas.field = 'bas';
- sub.field = 'sub';
- ?. '--test--bas--'; ?. bas.field; bas.test();
- ?. '--test--sub--'; ?. sub.field; sub.test();
--test--bas--
field
field
field
field
field
--test--sub--
field
field
field
field
CSub.method()..field
--test--bas--
bas
bas
bas
bas
bas
--test--sub--
sub
sub
sub
sub
CSub.method()..sub
下载该演示
4.4 运算符重载
- ########################################
- # class-operators-override
- ########################################
- # this['+'] = fun (right) { ... }
- # this['-'] = fun (right) { ... }
- # ...
- ########################################
-
- class Number(me)
- ..this['+'] = fun (you) {
- ....return me + you;
- ..};
-
- ..this['-'] = fun (you) {
- ....return me - you;
- ..};
-
- ..this['*'] = fun (you) {
- ....return me * you;
- ..};
-
- ..this['/'] = fun (you) {
- ....return me / you;
- ..};
-
- ..this['\'] = fun (you) {
- ....return me div you;
- ..};
-
- ..this['%'] = fun (you) {
- ....return me mod you;
- ..};
-
- ..this['^'] = fun (you) {
- ....return me ^ you;
- ..};
-
- ..this['='] = fun (you) {
- ....return me = you;
- ..};
-
- ..this['!'] = fun (you) {
- ....return me <> you;
- ..};
-
- ..this['>'] = fun (you) {
- ....return me > you;
- ..};
-
- ..this['<'] = fun (you) {
- ....return me < you;
- ..};
- end class;
-
- var n = Number(10);
- ?. n .+ 2; // .+ means + override version
- ?. n .- 3; // .- means - override version
- ?. n .* 4; // .* means * override version
- ?. n ./ 5; // ./ means / override version
- ?. n .\ 6; // .\ means \ override version
- ?. n .% 7; // .% means % override version
- ?. n .^ 8; // .^ means ^ override version
- ?. n .> 9; // .> means > override version
- ?. n .= 10; // .= means = override version
- ?. n .< 11; // .< means < override version
- ?. n .! 12; // .! means ! override version
-
- ########################################
- # 1. Currently FUN supports override operators(16):
- # + - * / \ % ^ ! = < > & ~ ? | #
- # 2. All override operators same precedence
- # 3. All override operators are duality operators
- # So the functions will have one parameter
- # 4. Must use "." append operators to use them
- ########################################
12
7
40
2
1
3
100000000
True
True
True
True
下载该演示
4.5 一切都是对象
一切都是对象, 包括数字, 字符串, 列表, 函数, 类等等.
- ########################################
- # object
- ########################################
-
- # number
- ?. (1.atan() * 2).sin();
-
- # string
- ?. '123'.length();
- ?. 'abc'.upper();
- ?. 'ABC'.lower();
-
- # set/list
- ?. [a: 1, b: 2, c: 3].a;
-
- var s1 = [
- ..f1: fun(){
- ....?. 'hello, f1';
- ..},
- ..f2: fun(){
- ....?. 'hello, f2';
- ..}
- ];
-
- s1.f1();
- s1.f2();
1
3
ABC
abc
1
hello, f1
hello, f2
下载该演示
5. 函数式编程
Fun 是一门函数式编程语言, 支持 first-class 和 higher-order 函数. Fun 也支持匿名函数, 闭包和 currying.
5.1 First-class 和高阶函数
- ########################################
- # functional
- ########################################
-
- fun foo(a)
- ..?. 'Hello, ' & a & '!';
- end fun;
-
- var f = foo;
- f('functional');
-
- fun high(f, a)
- ..f(a);
- end fun;
-
- var h = high;
- h(f, 'functional');
Hello, functional!
Hello, functional!
下载该演示
5.2 匿名函数
- ########################################
- # functional-anonymous
- ########################################
- # fun ( parameters ) { cmds }
- ########################################
- # fun ( ) { cmds }
- ########################################
- # ( ) { cmds }
- ########################################
- # { cmds }
- ########################################
-
- fun If(a, b, c)
- ..if a then
- ....return b();
- ..elsif c <> null then
- ....return c();
- ..end if;
- end fun;
-
- fun Loop(a, b)
- ..while a() do
- ....b();
- ..end do;
- end fun;
-
- fun For(init, cond, nex1, code)
- ..init();
- ..while cond() do
- ....code();
- ....nex1();
- ..end do;
- end fun;
-
- fun testIf()
- ..If(
- ....true,
- ....{?.true} # Anonymous function (Lambda calculus)
- ..);
-
- ..If(
- ....false,
- ....{?.false}, # Anonymous function (Lambda calculus)
- ....{?.true} # Anonymous function (Lambda calculus)
- ..);
- end fun;
- testIf();
-
- fun testLoop()
- ..var i = 0;
- ..var s = 0;
-
- ..Loop(
- ....{return i < 10}, # Anonymous function (Lambda calculus)
- ....{?, i; i += 1} # Anonymous function (Lambda calculus)
- ..);
- ..?. 'DONE';
-
- ..For(
- ....{i = 1; s = 0}, # Anonymous function (Lambda calculus)
- ....{@ = i <= 1000}, # Anonymous function (Lambda calculus)
- ....{i += 1}, # Anonymous function (Lambda calculus)
- ....{s += i} # Anonymous function (Lambda calculus)
- ..);
- ..?. s;
- end fun;
- testLoop();
-
- ########################################
- # 1. "@" is a built-in variable in "fun"
- # @ <- result
- # 2. {...} <- (){} <- fun(){}
- # with parameters must use
- # fun(parameters){} or
- # (parameters){}
- # 3. "?." means output (append extra \r\n)
- # "?," means output (append a blank' ')
- # "?:" means output (append a TAB )
- # "?" means output (without any extra)
- ########################################
True
True
0 1 2 3 4 5 6 7 8 9 DONE
500500
下载该演示
5.3 闭包
- ########################################
- # functional-closure
- ########################################
-
- fun counter()
- ..var i = 0;
- ..return fun(){
- ....i += 1;
- ....result = i;
- ..};
- end fun;
-
- var c = counter();
- ?. c();
- ?. c();
- ?. c();
-
- fun mul(bas)
- ..return fun(times){
- ....return bas * times;
- ..};
- end fun;
-
- var m = mul(3);
- ?. m(4);
- ?. m(5);
- ?. m(6);
1
2
3
12
15
18
下载该演示
5.4 Currying
- ########################################
- # functional-currying
- ########################################
- # fun name ( arguments )
- ########################################
-
- fun mul(bas, times)
- ..return bas * times;
- end fun;
-
- var m = fun mul(3);
- ?. m(4);
- ?. m(5);
- ?. m(6);
12
15
18
下载该演示
5.5 数学式函数
- ########################################
- # functional-mathematics
- ########################################
- # var name ( arguments ) = exp;
- ########################################
- # ( arguments ) -> exp
- # ( ) -> exp
- # argument -> exp
- # -> exp
- ########################################
-
- var ifv = (condition, vtrue, vfalse){
- ..if condition then
- ....return vtrue;
- ..else
- ....return vfalse;
- ..end if;
- };
-
- var forto = (start, end1, step1, action){
- ..result = 0;
- ..for i = start to end1 step step1 do
- ....result = action(i, result);
- ..end do;
- };
-
- var sqrt(n) = n ^ 0.5;
-
- var max(a, b) = ifv(a > b, a, b);
- var min(a, b) = ifv(a < b, a, b);
-
- var sqrt2 = n -> n ^ 0.5;
- var max2 = (a, b) -> ifv(a > b, a, b);
- var min2 = (a, b) -> ifv(a < b, a, b);
-
- var sum(s, e, i) = forto(s, e, i, (i, r) -> r + i);
- var sum1(n) = sum(1, n, 1);
- var fact(n) = forto(1, n, 1, (i, r) -> ifv(r=0, 1, r) * i);
-
- ?. sqrt(9);
- ?. max(1, 2);
- ?. min(1, 2);
- ?. sqrt2(9);
- ?. max2(1, 2);
- ?. min2(1, 2);
- ?. sum(1, 10000, 1);
- ?. sum1(10000);
- ?. fact(17);
3
2
1
3
2
1
50005000
50005000
355687428096000
下载该演示
6. 列表: 集合处理
Fun 内置了一个简单的方便的列表, 看起来像是数组, 字典, hash 表等. 类似的名词可以包括: 集合, 列表, 数组, 关联数组, hash, map, 字典等等. 在 Fun 语言里面这些全是同一个东西, 甚至函数, 类, 对象等全是.
6.1 数组
- ########################################
- # set
- ########################################
- # [ value, value, value ... ]
- ########################################
-
- var list = [0, 1, 2, 3, 4, 5];
-
- ?. 1 in list;
- ?. 3 in list;
- ?. 5 in list;
- ?. not 7 in list;
-
- for i in list do
- ..?, i;
- end do;
- ?. 'DONE';
-
- ?. list[0];
- ?. list[1];
- ?. list[-1];
- ?. list[-2];
-
- list[3] = -3;
- list[-1] = -5;
-
- for i in list do
- ..?, i;
- end do;
- ?. 'DONE';
-
- ########################################
- # 1. The elements can be anything includes base types and object types
- #
- # [num: 1, str: "string", time: @'2010-04-23 17:26:22', bool: false]
- #
- # [[name: 'fun', value: 'function'], [name: 'obj', value: 'object']]
- #
- # 2. Index of list start from 0 to N-1 and from -N to -1, as below:
- #
- # var N = list.count();
- #
- # [ 0 1 2 3 ... N-3 N-2 N-1 ]
- # ------------> ++1 --------->
- #
- # [ 0-N 1-N 2-N 3-N ... -3 -2 -1 ]
- # <------------ --1 <---------
- #
- # !!! Index must be Integer, Don't Use any Float or Double Index !!!
- ########################################
True
True
True
True
0 1 2 3 4 5 DONE
0
1
5
4
0 1 2 -3 4 -5 DONE
下载该演示
6.2 字典或者叫关联数组
在 Fun 语言中, 数组和字典或者 hash 表, 实际上是同一个东西, 区别在于你有没有给一个元素命名. 全部元素都没名字的看起来像是传统的数组, 全部命名的就像是传统的字典, 而且还可以有混合的. 对照前面的函数命名参数不难发现, 函数参数表实际上也是跟这个一样, 是同一种东西.
- ########################################
- # set-named
- ########################################
- # [ name: value, name: value ... ]
- ########################################
-
- var list = [red: 0x0000ff, green: 0x00ff00, blue: 0xff0000, 0xffff00, '黄色': 0xffff00, '显示': a -> a & '!', ];
-
- for i in list do
- ..?, i;
- end do;
- ?. 'DONE';
-
- ?, 'red';
- ?, list[0];
- ?, list['red'];
- ?. list.red;
-
- ?, 'green';
- ?, list[1];
- ?, list['green'];
- ?. list.green;
-
- ?, 'blue';
- ?, list[2];
- ?, list['blue'];
- ?. list.blue;
-
- list.yellow = 0x00ffff;
- list['white'] = 0xffffff;
- list["black"] = 0x000000;
-
- for i in list do
- ..?, i;
- end do;
- ?. 'DONE';
-
- ?. list.'黄色';
- ?. list.'显示'('多彩缤纷的世界你好');
255 65280 16711680 16776960 16776960 DONE
red 255 255 255
green 65280 65280 65280
blue 16711680 16711680 16711680
255 65280 16711680 16776960 16776960 65535 16777215 0 DONE
16776960
多彩缤纷的世界你好!
下载该演示
6.3 新建列表
列表或者叫数组在声明时, 类似于类的声明, 只有一个实例而已, 相当于静态变量. 如果想要不同的副本, 可以加 "new" 关键字或者内置的 @clone() 函数. 这在函数里面或者循环里面非常有用.
- ########################################
- # set-clone
- ########################################
- # new [...]
- ########################################
- # s.@clone()
- ########################################
-
- var s1 = new [1, 2, 3];
- s1.@each((i){?,i}); ?. null;
-
- var s2 = s1.@clone();
- s2.@each((i){?,i}); ?. null;
-
- s1[0] = 11;
- s2[1] = 22;
- s1.@each((i){?,i}); ?. null;
- s2.@each((i){?,i}); ?. null;
1 2 3
1 2 3
11 2 3
1 22 3
下载该演示
6.4 有关列表的库
- ########################################
- # lib-set
- ########################################
- # built-in (4)
- ########################################
- # s.@count ()
- # s.@each (fun, reverse = false) # fun (val) or (val, key)
- # s.@add (v1, v2, ...)
- # s.@clone ()
- ########################################
-
- var pathSet(set, path, value) = locate(set, path, value, 1);
- var pathInc(set, path, value) = locate(set, path, value, 2);
- fun locate(set, path, value, mode) // mode: 0-get, 1-set, 2-inc
- ..var lp = nil;
- ..for p in path do
- ....if lp <> nil then
- ......if set[lp] = nil then
- ........set[lp] = new [];
- ......end if;
- ......set = set[lp];
- ....end if;
- ....lp = p;
- ..end do;
- ..result = set[lp];
- ..if mode = 1 then
- ....set[lp] = value;
- ..elsif mode = 2 then
- ....set[lp] += value;
- ..end if;
- end fun;
-
- fun filter(s, f, n)
- ..var ret = n or new [];
- ..s.@each((v, k){
- ....if f(var v, k) then
- ......if k <> nil then
- ........ret[k] = v;
- ......else
- ........ret.@add(v);
- ......end if;
- ....end if;
- ..});
- ..result = ret;
- end fun;
-
- fun find(s, f)
- ..result = nil;
- ..for v in s do
- ....if f(v) then
- ......return v;
- ....end if;
- ..end do;
- end fun;
-
- fun compose(args, a)
- ..args.@each((f){
- ....a = f(a);
- ..}, true);
- ..return a;
- end fun;
-
- fun map(fn, list)
- ..var set = new [];
- ..list.@each( v -> set.@add(fn(v)) );
- ..result = set;
- end fun;
-
- fun fromPairs(list)
- ..var set = new [];
- ..list.@each( (v){
- ....set[v[0]] = v[1];
- ..});
- ..result = set;
- end fun;
-
- fun reducePairs(p, a)
- ..a = a or new [];
- ..for i = 0 to p.@count() -1 step 2 do
- ....a[p[i]] = p[i+1];
- ..end do;
- ..result = a;
- end fun;
-
- fun mapReduce(map, reduce, a)
- ..var ret;
- ..a.@each( v -> reduce(map(v), var ret) );
- ..result = ret;
- end fun;
- var mapReduceEx(map, reduce, preMap, a) = mapReduce(map, reduce, preMap(a));
-
- fun formats(str, set)
- ..result = str.replace(/\{(\w++)\}/g, (m){
- ....result = formats(set[m.@(1)], set);
- ..});
- end fun;
-
- var mergeJson = mergeSet;
- fun mergeSet(src, dst, isInc)
- ..for k: v in src do
- ....if k = nil then
- ......dst.@add(v);
- ....elsif dst[k] = nil then
- ......dst[k] = v;
- ....else
- ......try
- ........if v.@count() > 0 or dst[k].@count() > 0 then
- ..........mergeSet(v, dst[k], isInc);
- ........else
- ..........setRet();
- ........end if;
- ......except //?. @;
- ........setRet();
- ......end try;
- ....end if;
-
- ....fun setRet()
- ......try
- ........if isInc then
- ..........dst[k] += v * 1;
- ........else
- ..........dst[k] = v;
- ........end if;
- ......except
- ........dst[k] = v;
- ......end try;
- ....end fun;
- ..end do;
- end fun;
-
- # result = s2 - s1
- fun diffSet(s1, s2, ret)
- ..ret = ret or new [];
- ..result = ret;
-
- ..for k: v in s2 do
- ....if s1[k] = nil then
- ......setRet();
- ....else
- ......try
- ........if s2[k].@count() >= 0 and s1[k].@count() >= 0 then
- ..........var d = diffSet(s1[k], s2[k]);
- ..........if d then
- ............ret[k] = d;
- ..........end if;
- ........else
- ..........setRet();
- ........end if;
- ......except //?. @;
- ........setRet();
- ......end try;
- ....end if;
-
- ....fun setRet()
- ......if v <> s1[k] then
- ........if k = nil then
- ..........ret.@add(v);
- ........else
- ..........ret[k] = v;
- ........end if;
- ......end if;
- ....end fun;
- ..end do;
- end fun;
下载该库
- ########################################
- # test for lib-set.fun
- ########################################
-
- use '..\lib\lib-set.fun';
-
- test();
-
- fun test()
- ..?. [1, 2, 3].@count();
-
- ..[1, 2, 3].@each((i){?,i});
- ..?. 'DONE';
-
- ..var abc = [a: 1, b: 2, c: 3];
- ..abc.@each((i, k){?,k & '=' & i});
- ..?. 'DONE';
-
- ..abc.@add(4, 5, 6, g: 7, h: 8, i: 9)
- ......@each((i, k){?,k & '=' & i});
- ..?. 'DONE';
- end fun;
3
1 2 3 DONE
a=1 b=2 c=3 DONE
a=1 b=2 c=3 =4 =5 =6 g=7 h=8 i=9 DONE
下载该演示
6.5 JSON 格式
- ########################################
- # lib-json
- ########################################
- # built-in (2)
- ########################################
- # set.@toJson (format, json) # save set as JSON string
- # str.getJson (json = false) # load str as JSON set/list/tree
- ########################################
- # 1. format param of @toJson()
- # default 0, format levels
- # join (concat) if format = -1
- # 2. json param of @toJson()
- # default false, name quoted as "name"
- ########################################
-
- fun JSON()
- ..fun Parse(s)
- ....result = s.getJson(json: true);
- ..end fun;
-
- ..fun Stringify(s, level)
- ....result = s.@toJson(level, json: true);
- ..end fun;
- end fun;
下载该库
- ########################################
- # test for lib-json.fun
- ########################################
-
- use '..\lib\lib-json.fun';
-
- test();
-
- fun test()
- ..var s1 = '[1, 2, 3]'.getJson();
- ..s1.@each((i){?,i});
- ..?. '';
- ..?. s1.@toJson();
-
- ..var s2 = "[{key: str, val: 'this is a string.'},
- {key: num, val: 123456789}]".getJson();
- ..s2.@each(
- ....(i){
- ......i.@each(
- ........(v, k){
- ..........?, k & ': ' & v;
- ........}
- ......);
- ......?. null;
- ....}
- ..);
- ..?. 'format: 0';
- ..?. s2.@toJson();
- ..?. 'format: 1 level';
- ..?. s2.@toJson(format: 1);
- ..?. 'format: 2 levels';
- ..?. s2.@toJson(format: 2);
- end fun;
1 2 3
[1,2,3]
key: str val: this is a string.
key: num val: 123456789
format: 0
[{key:"str",val:"this is a string."},{key:"num",val:123456789}]
format: 1 level
[
{key:"str",val:"this is a string."},
{key:"num",val:123456789}
]
format: 2 levels
[
{
key: "str",
val: "this is a string."
},
{
key: "num",
val: 123456789
}
]
下载该演示
7. 正则表达式
Fun 支持 Perl 兼容的正则表达式(PCRE).
7.1 语法
正则表达式看起来像这样 /[^\/\s]+/[gimsux]*, %[^\%\s]+%[gimsux]* 和 $("[^"]+"|'[^']+'|`[^`]+`)[gimsux]* (正则表达式). 你还可以把一个字符串用 toRegex(选项) 函数来转成正则表达式.
Fun 语言内置 match() 和 replace(), 像是 str.match(re) 或者 re.match(str).
还有正则表达式运算符: =~ (判断匹配) 和 !~ (判断不匹配).
7.2 正则表达式库 (match and replace)
- ########################################
- # lib-regex
- ########################################
- # built-in (3)
- ########################################
- # match:
- # str.match(str) # match only in string form
- #
- # str.match(reg) # match in regex pattern
- # reg.match(str) # match in regex pattern
- # str.match(reg, action) # match in regex pattern
- # reg.match(str, action) # match in regex pattern
- #
- # replace:
- # str.replace(str, newstr) # replace all in string form
- #
- # str.replace(reg, newone) # replace in regex pattern
- # reg.replace(str, newone) # replace in regex pattern
- #
- # toRegex:
- # str.toRegex(options) # options: g, i, m, s, u, x
- ########################################
- # 1. str: string
- # reg: regex
- # 2. if 'g' in regex option, match() return a list of matched string
- # if action exists, the action will be performed with a match
- # object argument for every match, and return string concated
- # from the return value of the action
- # or, match() return a match object with all matched groups
- # (matched string is 0 of the groups)
- # if action exists, the action will be performed with the match
- # object one time, and return string from the return value of
- # the action
- # 3. if newone is string, replace with the string one time or all
- # (according to 'g')
- # or if newone is action (function), replace with the return value
- # of the action
- # 4. options:
- # g - global, match or replace all
- # i - ignore case, case insensitive
- # m - multiple lines, ^ and $ match start or end of any line
- # s - single line, dot(.) match any character, even newline(\n)
- # u - UTF8
- # x - extended, allow regex to contain extra whitespace and comments
- # e.g.: '\d+'.toRegex('g')
- ########################################
-
- # return left string, the right argument must be var right, e.g.:
- # var right = '';
- # var left = splitonce(/\./, 'a.b', var right);
- # // Now, left = a, right = b
- var splitonce(re, str, right) = re.match(str, (m){
- ....@ = m.missed();
- ....right = m.rest();
- ..});
-
- # return a list
- var split = (re, str){
- ......result = new [];
- ......var m = re.match(str);
- ......while m.@@() <> nil loop
- ........result.@add(m.missed());
- ........m.match();
- ......end loop;
- ......result.@add(m.missed());
- };
下载该库
- ########################################
- # test for lib-regex.fun
- ########################################
-
- use '..\lib\lib-regex.fun';
-
- test();
-
- fun test()
- ..# str.match(str), return bool
- ..?, 'abcd123efg' =~ '123';
- ..?, 'abcd123efg' !~ '1234';
- ..?, 'abcd123efg' .match( '123' );
- ..?. not 'abcd123efg' .match( '1234' );
-
- ..# str.match(reg), reg.match(str), return bool
- ..?, not not 'abcd123efg' =~ /123/; # Convert to bool
- ..?, /1234/ !~ 'abcd123efg';
- ..?, not not 'abcd123efg' .match( /123/ );
- ..?. not '1234'.toRegex().match( 'abcd123efg' );
-
- ..# g, return list of matched string
- ..'abcd123efg'.match(/\d/g).@each((m){? '[' & m & ']'});
- ..?. null;
-
- ..# not g, return match object
- ..?. 'abcd123efg'.match(/\d+/).value();
-
- ..# str.match(reg, action), reg.match(str, action)
- ..# return string concated from return value of action
- ..?. 'abcd123efg'.match(/\d/g, (m){@= '[' & m.value() & ']'});
- ..?. 'abcd123efg'.match(/\d/i, (m){@= '[' & m.value() & ']'});
-
- ..# str.replace(str, newstr)
- ..?. 'abcd123efg'.replace('123', '[123]');
-
- ..# str.replace(reg, newstr), reg.replace(str, newstr)
- ..?. 'abcd123efg'.replace(/\d/g, '[$0]');
-
- ..# str.replace(reg, action), reg.replace(str, action)
- ..?. 'abcd123efg'.replace(/\d/g, (m){@= '[' & m.value() * 3 & ']'});
-
- ..var right = '';
- ..var left = splitonce(/\./, 'a.b', var right);
- ..?. 'left: [$left], right: [$right]'.eval();
-
- ..split('a.b.c.d', /\./).@each((m){?, '[' & m & ']'});
- ..?. null;
- end fun;
True True True True
True True True True
[1][2][3]
123
[1][2][3]
[1]
abcd[123]efg
abcd[1][2][3]efg
abcd[3][6][9]efg
left: [a], right: [b]
[a] [b] [c] [d]
下载该演示
7.3 匹配对象
match() 函数会返回一个匹配对象(没带 'g' 选项和 action 参数时). match() 和 replace() 的 action 函数都有一个匹配对象参数.
- ########################################
- # lib-match (match object)
- ########################################
- # built-in (6)
- ########################################
- # m.match() # perform next match, return success or not
- #
- # m.missed() # return string missed (Left string of matched)
- # m.value() # return string matched
- # m.value(substi) # return string substitute
- # m.@@() # return string matched
- # m.@@(substi) # return string substitute
- # m.rest() # return string rest (All right string)
- #
- # m.gcount() # return group count
- #
- # m.groups(num) # return group by index
- # m.groups(str) # return group by name
- # m.@(num) # group by index
- # m.@(str) # group by name
- ########################################
下载该库
- ########################################
- # test for lib-match.fun
- ########################################
-
- use '..\lib\lib-match.fun';
-
- test();
-
- fun test()
- ..var m = 'a.b.c.d' =~ /\./;
- ..loop
- ....print(m.missed(), 'missed');
- ....print(m.value(), 'value');
- ....print(m.@@(), '@@');
- ....print(m.rest(), 'rest');
- ....?. null;
- ....exit when not m.match();
- ..end loop;
- ..print(m.missed(), 'missed');
- ..?. null;
-
- ..m = 'a.b.c' =~ /^(?P<first>\w)\.(\w)\.(\w)$/;
- ..print(m.gcount(), 'Count');
- ..print(m.groups('first'), 'first');
- ..?. null;
- ..for i = 0 to m.gcount() - 1 do
- ....print(m.@(i), i);
- ..end do;
- ..?. null;
-
- ..fun print(str, name)
- ....?, '$name: [$str]'.eval();
- ..end fun;
- end fun;
missed: [a] value: [.] @@: [.] rest: [b.c.d]
missed: [b] value: [.] @@: [.] rest: [c.d]
missed: [c] value: [.] @@: [.] rest: [d]
missed: [d]
Count: [4] first: [a]
0: [a.b.c] 1: [a] 2: [b] 3: [c]
下载该演示
- //Outer brackets: \((\d++(?:\.\d++)?|(?R))(?:[+\-*/](?1))++\)
- // Simplify: \((\d+(\.\d+)?|(?R))([+\-*/](?1))+\)
- //Inner brackets: ((\d++(?:\.\d++)?|(?3))(?:[+\-*/](?2))++)|(\((?1)\))
- // Simplify: ((\d+(\.\d+)?|(?5))([+\-*/](?2))+)|(\((?1)\))
- var re = $'
- (
- (\d++(?:\.\d++)? | (?3))
- (?: [+\-*/]
- (?2)
- )++
- )
- |
- ( \( (?1) \) )
- 'x;
-
- ?. re.match('(((1+2-3)*4/5)-((1+2)-((3*4)/((5+(6-7))*(8/9+10.1)/11.2))))').@@();
(((1+2-3)*4/5)-((1+2)-((3*4)/((5+(6-7))*(8/9+10.1)/11.2))))
下载该演示
8. 库
Fun 提供了一个轻量级的基本库, 包括数学运算, 字符串和时间/日期处理, Windows API/COM, 列表处理和正则表达式等 ...
8.1 数学库
- ########################################
- # lib-base
- ########################################
-
- fun ifval (condition, vtrue, vfalse)
- ..if condition then
- ....return vtrue;
- ..else
- ....return vfalse;
- ..end if;
- end fun;
- var ifv = ifval;
- var ifb(c) = ifv(c, true, false);
- var iff(c, t, f) = ifv(c(), t, f);
- var iffa(c, t, f) = ifa(c(), t, f);
-
- fun ifa (condition, atrue, afalse)
- ..if condition then
- ....return atrue ();
- ..else
- ....return afalse();
- ..end if;
- end fun;
-
- fun forloop (start, end1, step1, action, set)
- ..result = set;
- ..for i = start to end1 step step1 do
- ....result = action(i, result) or result;
- ..end do;
- end fun;
- var forto = forloop;
- var forE(num, action, set) = forto(1, num, 1, action, set);
-
- var filter = (start, end1, step1, cond, action){
- ..result = [];
- ..forto(start, end1, step1, (i, ret){
- ....if cond(i, ret) then
- ......action(i, ret);
- ....end if;
- ....result = ret;
- ..}, result);
- };
- var filter1(s, e, c, a) = filter(s, e, 1, c, a);
-
- fun foreach (set1, action)
- ..for k: v in set1 do
- ....action(v, k);
- ..end do;
- end fun;
- var forin = foreach;
下载该库
- ########################################
- # lib-math
- ########################################
- # built-in (6)
- ########################################
- # a.exp () # e ^ a
- # a.log () # LogE(a)
- # a.sin ()
- # a.cos ()
- # a.atan ()
- # a.random () # 1.random(), 0.random(), a.random(), -1.random(seed = 0)
- ########################################
-
- #use 'lib-base.fun';
-
- var pow(a, b) = a ^ b;
- var sqrt(a) = a ^ 0.5;
-
- var exp(a) = a.exp();
- var log(a) = a.log();
- var log2(a) = a.log() / 2.log();
- var log10(a) = a.log() / 10.log();
-
- var sin(a) = a.sin();
- var cos(a) = a.cos();
- var tan(a) = a.sin() / a.cos();
- var atan(a) = a.atan();
- var asin(a) = atan(a / sqrt(1 - a ^ 2));
- var acos(a) = atan(a / sqrt(1 - a ^ 2) * -1) + 2 * atan(1);
-
- var pi() = 1.atan() * 4;
- var e() = 1.exp();
- var phi() = (5^0.5+1)/2;
-
- #var max(a, b) = ifv(a > b, a, b);
- #var min(a, b) = ifv(a < b, a, b);
- #var abs(a) = ifv(a < 0, a * -1, a);
- var max(a, b) = a > b and a or b;
- var min(a, b) = a < b and a or b;
- var abs(a) = a < 0 and a * -1 or a;
- //var round(a) = a div 1;
- var round(a, b) = a * 10^b div 1 / 10^b;
- var floor(a) = a div 1 > a and a div 1 - 1 or a div 1;
- var ceil(a) = a div 1 < a and a div 1 + 1 or a div 1;
-
- var gcd(x, y) = y and gcd(y, x mod y) or x;
- var lcm(x, y) = x * y / gcd(x, y);
-
- var random() = 1.random(); # return x in 0..1
- var randomize() = 0.random();
- var randomint(a) = a.random(); # return x in 0..a
下载该库
- ########################################
- # test for lib-math.fun
- ########################################
-
- use '..\lib\lib-math.fun';
-
- test();
-
- fun test()
- ..?, 8 = pow(2, 3);
- ..?, 2 = sqrt(4);
- ..?, e() = exp(1);
- ..?, 2 = log(exp(2));
- ..?, 3 = log2(pow(2, 3));
- ..?. 4 = log10(pow(10, 4));
-
- ..?, 0.000001 > abs(1 - sin(pi() / 6) * 2);
- ..?, 0.000001 > abs(1 - cos(pi() / 3) * 2);
- ..?, 0.000001 > abs(1 - tan(pi() / 4));
- ..?, 0.000001 > abs(pi() - atan(sqrt(3)) * 3);
- ..?, 0.000001 > abs(pi() - asin(sqrt(3) / 2) * 3);
- ..?. 0.000001 > abs(pi() - acos(sqrt(3) / 2) * 6);
-
- ..?, pi();
- ..?. e();
-
- ..?, 9 = max(1, 9);
- ..?, 1 = min(1, 9);
- ..?, 1 = abs(-1);
- ..?, 1 = round(1.4);
- ..?, 1 = round(1.4999);
- ..?. 2 = round(1.5);
-
- ..randomize();
- ..?, random() < 1;
- ..?, random() < 1;
- ..?, random() < 1;
- ..?, randomint(100) < 100;
- ..?, randomint(100) < 100;
- ..?. randomint(100) < 100;
- end fun;
True True True True True True
True True True True True True
3.14159265358979 2.71828182845905
True True True True True True
True True True True True True
下载该演示
8.2 字符串库
- ########################################
- # lib-string
- ########################################
- # built-in (9)
- ########################################
- # a.length ()
- # a.lower ()
- # a.upper ()
- # a.subpos (sub)
- # a.substr (pos, len) # Default pos=0, len=MAX, can be negative
- # a.move (ptr) # ptr: int, copy to ptr
- # a.x (n) # Replicate n times, or reverse (n = -1)
- # # sort (n = -2)
- # a.escape () # \ abtvrnf'"?/\ \x HH \u HHHH
- # a.format (A1, A2, ... An) # %s
- # a.eval () # $id
- ########################################
- # 1. a.escape()
- # \a \b \t \v \r \n \f
- # \' \" \? \/ \\
- # \xHH \uHHHH
- ########################################
下载该库
- ########################################
- # test for lib-string.fun
- ########################################
-
- use '..\lib\lib-string.fun';
-
- test();
-
- fun test()
- ..var a = 'Www.FunLang.Org';
-
- ..?. a.length();
- ..?. a.lower();
- ..?. a.upper();
-
- ..var b = a.lower();
- ..?. b.subpos('fun');
- ..?. b.substr();
- ..?. b.substr(4);
- ..?. b.substr(4, 7);
- ..?. b.substr(len: 3);
- ..?. b.substr(4, -8);
- ..?. b.substr(-3);
-
- ..?. a.substr(4, 7).x(3);
-
- ..var c = '[Hello\t\\\r\n\?\x40]';
- ..?. c;
- ..?. c.escape();
-
- ..var d = 'Error: %s at %s/%s.';
- ..?. d;
- ..?. d.format('"a" not found', 10, 3);
-
- ..var name = 'David';
- ..var e = 'Hello, $name.';
- ..?. e;
- ..?. e.eval();
- end fun;
15
www.funlang.org
WWW.FUNLANG.ORG
4
www.funlang.org
funlang.org
funlang
www
funlang
org
FunLangFunLangFunLang
[Hello\t\\\r\n\?\x40]
[Hello \
?@]
Error: %s at %s/%s.
Error: "a" not found at 10/3.
Hello, $name.
Hello, David.
下载该演示
8.3 时间和日期
- ########################################
- # lib-time
- ########################################
- # built-in (2)
- ########################################
- # a.time () # 0.time(), a.time()
- # a.format() # yyyy-mm-dd hh:nn:ss:zzz
- ########################################
-
- var date() = 1.time(); # return date & time
- var time() = 0.time(); # return time
- var ms = 24 * 60 * 60 * 1000;
-
- class tick()
- ..var t = time();
- ..var get = {
- ....result = (time() - t) * ms div 1;
- ....t = time();
- ..};
- ..var getStr = {
- ....result = get();
- ....if result < 100 then
- ......result = result div 1 & ' milliseconds';
- ....elsif result < 1000 * 60 then
- ......result = result div 100 / 10 & ' seconds';
- ....elsif result < 1000 * 60 * 60 then
- ......result = result / 1000 div 6 / 10 & ' minutes';
- ....else
- ......result = result / 60000 div 6 / 10 & ' hours';
- ....end if;
- ..};
- ..var show = (s, ms){
- ....if ms = 0 then ms = 1; end if;
- ....result = s & ': ' & get() / ms;
- ..};
- end class;
-
- fun diffDate(y, m, d, default, diff, now)
- ..now = now or 1.time();
- ..result = default;
- ..try
- ....var mm = 'mm';
- ....var dd = 'dd';
- ....if diff in ['m', 'y'] then
- ......dd = 15;
- ......d = 15;
- ....end if;
- ....if diff = 'y' then
- ......mm = 7;
- ......m = 7;
- ....end if;
- ....result = now.format('yyyy-$mm-$dd'.eval()).toTime() - '$y-$m-$d'.eval().replace(/[^\d\-]++/g, '').toTime();
- ....if diff = 'm' then
- ......result = result / 30.436875 div 1;
- ....elsif diff = 'y' then
- ......result = result / 365.2425 div 1;
- ....end if;
- ..except
- ..end try;
- end fun;
下载该库
- ########################################
- # test for lib-time.fun
- ########################################
-
- use '..\lib\lib-time.fun';
-
- test();
-
- fun test()
- ..?. date();
- ..?. time();
-
- ..var t = tick();
- ..var s = 0;
- ..for i = 1 to 1000000 do
- ....s += i;
- ..end do;
- ..?, s;
- ..?. t.get();
- end fun;
2023-8-26 14:42:11
14:42:11
500000500000 156
下载该演示
8.4 文件操作
- ########################################
- # lib-file
- ########################################
- # built-in (8)
- ########################################
- # f.load ()
- # f.save (str, cp = 0, append = false) # cp 10056 - utf8 without bom
- # f.find (sub = false) # find directory if f endswith '\'
- # f.copy (f2, f3, ...)
- # f.move (f2) # delete f if f2 = null
- # f.time (flag) # flag: 0-CreationTime, 1-LastWriteTime
- # f.size ()
- # f.hash (mode) # mode: 0-MD5, 1-SHA1
- ########################################
下载该库
- ########################################
- # test for lib-file.fun
- ########################################
-
- use '..\lib\lib-file.fun';
-
- test();
-
- fun test()
- ..var f1 = 'c:\temp\admin\a.tmp';
- ..var f2 = 'c:\temp\admin\b.tmp';
- ..var f3 = 'c:\temp\admin\c.tmp';
- ..var fn = 'c:\temp\admin\?.tmp';
-
- ..f1.save('Hello, FUN.');
- ..?. f1.load();
-
- ..f1.copy(f2, f3);
- ..?. f2.load();
- ..?. f3.load();
-
- ..use '..\lib\lib-base.fun';
-
- ..foreach(fn.find(), (f){?.f});
-
- ..f1.move();
- ..f2.move();
- ..f3.move();
-
- ..foreach(fn.find(), (f){?.f});
- end fun;
Hello, FUN.
Hello, FUN.
Hello, FUN.
c:\temp\admin\a.tmp
c:\temp\admin\b.tmp
c:\temp\admin\c.tmp
下载该演示
8.5 Windows API
- ########################################
- # lib-winapi
- ########################################
- # built-in (2)
- ########################################
- # f.getapi(name, type)
- ########################################
- # f.@toCallback(nil, type, ptr)
- # f.@toCallback(obj, type, ptr)
- ########################################
- # 1. f.getapi(name, type)
- # f: file name (.dll)
- # name: proc name or address
- # type: xxx...:x
- # n(umber) i(nt) l(ong)
- # s(tring) w(idestr) a(nsistr) r(awstr)
- # p(ointer) v(oid) c(allback)
- # 2. how to call?
- # method.call() or method()
- #
- # e.g.:
- #
- # # get API
- # var msgbox = 'user32'.getapi('MessageBox', 'issi:i');
- #
- # # call via method.call()
- # msgbox.call(0, 'Hello, world!', 'Welcome...', 1);
- #
- # # or call via method()
- # msgbox(0, 'Hello, world!', 'Welcome...', 1);
- # 3. f.@toCallback(obj, type, ptr)
- # f # fun (function)
- # obj # object
- # type: xxx...:x # W - BSTR (OleString)
- # ptr: true or false # default false
- ########################################
下载该库
- ########################################
- # test for lib-winapi.fun
- ########################################
-
- use '..\lib\lib-winapi.fun';
-
- test();
-
- fun test()
- ..# constants
- ..var WM_SETTEXT = 12;
- ..var user32 = 'user32';
-
- ..# get APIs
- ..var findwin = user32.getapi('FindWindow', 'ss:i');
- ..var sendmsg = user32.getapi('SendMessage', 'iiip:i');
- ..var gettext = user32.getapi('GetWindowText', 'ipi:i');
-
- ..# settxt call sendmsg() - WM_SETTEXT
- ..var settxt(h, t) = sendmsg(h, WM_SETTEXT, 0, t);
-
- ..# gettxt call gettext()
- ..var gettxt = (h){
- ....result = ' '.x(256);
- ....var len = gettext(h, var result, 255);
- ....result = result.substr(len: len);
- ..};
-
- ..# call findwin via findwin.call()
- ..var handle = findwin.call('Shell_TrayWnd', '');
-
- ..# call settxt
- ..settxt(handle, 'New text.');
-
- ..# call gettxt
- ..?. '[' & gettxt(handle) & ']';
-
- ..# call settxt
- ..settxt(handle, '');
-
- ..# call gettxt
- ..?. '[' & gettxt(handle) & ']';
- end fun;
[New text.]
[]
下载该演示
8.6 Windows COM
- ########################################
- # lib-winole
- ########################################
- # built-in (2)
- ########################################
- # c.newobj(get = false)
- ########################################
- # f.@toEvent()
- # f.@toEvent(obj)
- # f.@toEvent(obj, Source, EventID, DispIDs)
- ########################################
- # 1. c.newobj(get = false)
- # c: class name or id
- # get: get an existing COM object
- # 2. Call method of ActiveX Object
- # obj.Method()
- # 3. Property get - @Property
- # x = obj.Property # or
- # x = obj.@Property() # or
- # x = obj.@Property(...) # for Property with params
- # 4. Property set - @@Property
- # obj.Property = x # or
- # obj.@@Property(x) # or
- # obj.@@Property(..., x) # for Property with params
- # 5. f.@toEvent()
- # f # fun (function)
- # obj # object
- # Source # Windows COM Object
- # EventID # IID
- # DispIDs # DispID(s)
- ########################################
下载该库
- ########################################
- # test for lib-winole.fun
- ########################################
-
- use '..\lib\lib-winole.fun';
- use '..\lib\lib-base.fun';
-
- test();
-
- fun test()
- ..var f1 = 'c:\temp\admin\1.tmp';
- ..var f2 = 'c:\temp\admin\2.tmp';
- ..var fn = 'c:\temp\admin\?.tmp';
-
- ..# Create ActiveX Object
- ..var sh = 'Wscript.Shell'.newobj();
-
- ..f1.save('Windows COM');
-
- ..# Call Method of COM Object
- ..sh.Run('cmd.exe /Ccopy %s %s'.format(f1, f2), 0, true);
-
- ..?. f2.load();
-
- ..foreach(fn.find(), (f){?.f; f.move()});
-
- ..var regex = 'VBScript.RegExp'.newobj();
- ..regex.Pattern = '^\d+$'; # Property set, or:
- ............................# regex.@@Pattern('^\d+$');
- ..?. regex.Pattern; # Property get, or:
- ............................# ?. regex.@Pattern();
- ..?. regex.Test('123'); # Call method
- ..?. regex.Test('abc');
- end fun;
Windows COM
c:\temp\admin\1.tmp
c:\temp\admin\2.tmp
^\d+$
True
False
下载该演示
8.7 类型转换
- ########################################
- # lib-type
- ########################################
- # built-in (5)
- ########################################
- # a.toStr(index) # index: default 0, for array; -2: Unicode
- # a.toNum(ptr) #1-int, 2-float, 3-double, -1:ptr
- # a.toTime()
- # a.toByte(pos) # default 0
- # a.toChar()
- # a.fromByte(pos, byte)
- ########################################
下载该库
- ########################################
- # test for lib-type.fun
- ########################################
-
- use '..\lib\lib-type.fun';
-
- test();
-
- fun test()
- ..?. 123.toStr() & 456.toStr(); # Auto conversion, same to 123 & 456
- ..?. '123'.toNum() * 2; # Auto conversion, same to '123' * 2
-
- ..?. '2010-05-12 15:53:59'.toTime() + 100;
- ..?. 'a'.toByte();
- ..?. 0x41.toChar();
-
- ..if [] then # Auto convert to false
- ....?. '[]';
- ..else
- ....?. 'not []'; # HIT
- ..end if;
-
- ..if [1, 2, 3] then # Auto convert to true
- ....?. '[1, 2, 3]'; # HIT
- ..else
- ....?. 'not [1, 2, 3]';
- ..end if;
-
- ..if 'true' or 'yes' or 'NOT_BLANK' then # true <- true, yes, or other NOT BLANK string
- ....?. 'true or yes or NOT_BLANK';
- ..elsif 'false' or 'no' or '' then # false <- false, no, or BLANK
- ....?. 'false or no or BLANK';
- ..end if;
- end fun;
123456
246
2010-8-20 15:53:59
97
A
not []
[1, 2, 3]
true or yes or NOT_BLANK
下载该演示
8.8 动态脚本
- ########################################
- # lib-dyns
- ########################################
- # built-in (1)
- ########################################
- # a.compile(inline = false) # file or string
- ########################################
- # a: file or string
- # inline: compile inline to access the current scope
- ########################################
下载该库
- ########################################
- # test for lib-dyns.fun
- ########################################
-
- use '..\lib\lib-dyns.fun';
-
- test();
-
- fun test()
- ..// compile a file
- ..var a = 'lib-file-test.fun'.compile();
- ..a(); // execute lib-file-test.fun
- ..a.test(); // call test() in lib-file-test.fun
-
- ..// compile a string
- ..var b = '?. 1 + 2;'.compile();
- ..b();
-
- ..// compile a string inline
- ..var c = 'b();'.compile(inline: true);
- ..c(); // call b() in the current scope
- end fun;
Hello, FUN.
Hello, FUN.
Hello, FUN.
c:\temp\admin\a.tmp
c:\temp\admin\b.tmp
c:\temp\admin\c.tmp
Hello, FUN.
Hello, FUN.
Hello, FUN.
c:\temp\admin\a.tmp
c:\temp\admin\b.tmp
c:\temp\admin\c.tmp
3
3
下载该演示
- var s = `var s = `$s`; ?. s.eval();`; ?. s.eval();
var s = `var s = `$s`; ?. s.eval();`; ?. s.eval();
下载该演示
9. 附录
-
9.1 演示
- #*======================================
- ....FFFFFFFF UU UU NN NN
- ....FF UU UU NNN NN
- ....FFFFFFF UU UU NN N NN
- ....FF UU UU NN N NN
- ....FF UU UU NN NNN
- ....FF UUUUUU NN NN
- ##======================================
-
- var out = output();
- class output()
- ..var head = (s){?. s & '.'.x(20-s.length())};
- ..var body = (s){?, ' '; ?. s};
- ..fun close()
- ....head('end');
- ....? '\r\n'.escape();
- ..end fun;
- end class;
-
- var idx;
- fun closure(o)
- ..var i = 0;
- ..return {
- ....o.body('index $i'.eval());
- ....result = i;
- ....i += 1;
- ..};
- end fun;
-
- fun test(n, f)
- ..out.head(n);
- ..idx = closure(out);
- ..f();
- ..out.close();
- end fun;
-
- test('if', {
- ..if idx() > idx() and idx() <= idx() then # short-circuit
- ....out.body('wrong');
- ..elsif idx() < idx() or idx() >= idx() then # short-circuit
- ....out.body('right');
- ..elsif idx() = idx() xor idx() <> idx() then
- ....out.body('error');
- ..else
- ....out.body('error');
- ..end if;
- });
-
- test('case', {
- ..case idx() is # @ <- idx()
- ....when idx() do
- ......out.body('wrong x()');
- ....when [idx(), idx()] do // or when new ...
- ......out.body('wrong [x]');
- ....when '^(%s)$'.format(idx()).toRegex() do
- ......out.body('wrong /x/');
- ....when '^($@)$'.eval().toRegex() do
- ......out.body('right /x/');
- ....when idx() do
- ......out.body('error');
- ....else
- ......out.body('error');
- ..end case;
- });
-
- test('loop', {
- ..loop
- ....exit when idx() < idx();
- ..end loop;
-
- ..for i = idx() to idx() step idx() loop
- ....out.body((i = 2) & ' - ' & i);
- ..end loop;
-
- ..for k: i in [a: idx(), b: idx(), c: idx()] do // or in new ...
- ....out.body('$k: $i'.eval());
- ..end do;
-
- ..while idx() < idx() do
- ....next when idx() mod 2 = 0;
- ....exit when idx() < idx();
- ..end do;
-
- ..out.body(idx() = 16);
- });
-
- test('try', {
- ..try
- ....var error() = 1 / 0;
- ....idx(); error(); idx();
- ..except # @ <- exception
- ....out.body('$@ at $@@()'.eval()); # eval $@@ as the last error
- ..finally
- ....out.body('final'.x(-1)); # reverse: a.x(-1)
- ..end try;
- });
if..................
index 0
index 1
index 2
index 3
right
end.................
case................
index 0
index 1
index 2
index 3
index 4
right /x/
end.................
loop................
index 0
index 1
index 2
index 3
index 4
True - 2
index 5
index 6
index 7
a: 5
b: 6
c: 7
index 8
index 9
index 10
index 11
index 12
index 13
index 14
index 15
index 16
True
end.................
try.................
index 0
Floating point division by zero at error/89()
lanif
end.................
下载该演示
9.2 下载
Fun.zip
9.3 无聊的试验: 汉语中文编程
- #===========================================================
- #
- # 测试中文编程
- #
- # 测试方法: funu.exe <本文件> -key:key_cn.ini
- #
- #===========================================================
-
- 如果 真 则
- ..?. 真; # 中
- 结束 如果;
-
- 如果 假 则
- ..?. 假;
- 再如 真 则
- ..?. 真; # 中
- 否则
- ..?. '肯定是哪里出错了!';
- 结束 如果;
-
- 变量 甲 = 1;
-
- 当 甲 是
- ..有 1 执行
- ....?. 1; # 中
- ..有 2 执行
- ....?. 2;
- ..有 3 执行
- ....?. 3;
- ..否则
- ....?. '否则';
- 结束 当;
-
- 甲 = '你好';
-
- 当 甲 是
- ..有 '好' 执行
- ....?. '很好很强大!';
- ..有 '坏' 执行
- ....?. '很黄很暴力!';
- ..有 '你好' 执行
- ....?. @ & ', 世界!'; # 中
- ..否则
- ....?. @ & '在哪里? 很傻很天真!';
- 结束 当;
-
- 甲 = 1;
-
- 循环
- ..?. 甲;
- ..跳出;
- 结束 循环;
-
- 循环
- ..跳出 有 甲 > 9;
- ..? 甲;
- ..甲 += 1;
- 结束 循环;
- ?. '..搞定';
-
- 甲 = 9;
-
- 循环
- ..甲 -= 1;
- ..跳出 有 甲 <= 0;
- ..跳过 有 甲 取余 2 = 1;
- ..? 甲;
- 结束 循环;
- ?. '..搞定';
-
- 甲 = 1;
-
- 以 甲 <= 9 循环
- ..? 甲;
- ..甲 += 1;
- 结束 循环;
- ?. '..搞定';
-
- 甲 = 9;
-
- 以 甲 > 0 执行
- ..? 甲;
- ..甲 -= 1;
- 结束 执行;
- ?. '..搞定';
-
- 设 甲 = 1 到 9 循环
- ..? 甲;
- 结束 循环;
- ?. '..搞定';
-
- 设 甲 = 9 到 1 递增 -1 执行
- ..? 甲;
- 结束 执行;
- ?. '..搞定';
-
- 设 甲 属于 [1, 2, 3, 4, 5] 循环
- ..? 甲;
- 结束 循环;
- ?. '..搞定';
-
- 设 甲 属于 [5, 4, 3, 2, 1] 执行
- ..? 甲;
- 结束 执行;
- ?. '..搞定';
-
- 尝试
- ..? '尝试..'; # 中
- 出错
- ..? '出错..';
- 结束 尝试;
- ?. '搞定';
-
- 尝试
- ..? '尝试..'; # 中
- 收尾
- ..? '收尾..'; # 中
- 结束 尝试;
- ?. '搞定';
-
- 尝试
- ..? '尝试..'; # 中
- 出错
- ..? '出错..';
- 收尾
- ..? '收尾..'; # 中
- 结束 尝试;
- ?. '搞定';
-
- 尝试
- ..? '尝试..'; # 中
- ..? 1 / 0;
- ..? '1 / 0';
- 出错
- ..? '出错..'; # 中
- ..? @ & '..'; # 中
- 收尾
- ..? '收尾..'; # 中
- 结束 尝试;
- ?. '搞定';
-
- 尝试
- ..? '尝试..'; # 中
- ..抛出 "停止!";
- ..? '停止!';
- 出错
- ..? '出错..'; # 中
- ..? @ & '..'; # 中
- 收尾
- ..? '收尾..'; # 中
- 结束 尝试;
- ?. '搞定';
True
True
1
你好, 世界!
1
123456789..搞定
8642..搞定
123456789..搞定
987654321..搞定
123456789..搞定
987654321..搞定
12345..搞定
54321..搞定
尝试..搞定
尝试..收尾..搞定
尝试..收尾..搞定
尝试..出错..Floating point division by zero..收尾..搞定
尝试..出错..停止!..收尾..搞定
下载该演示
- 且=and
- 为=as
- 以=while
- 位=bit
- 假=false
- 再如=elsif
- 出错=except
- 函数=fun
- 则=then
- 到=to
- 单线=atom
- 取余=mod
- 变量=var
- 否则=else
- 如果=if
- 尝试=try
- 属于=in
- 异或=xor
- 引用=use
- 当=case
- 循环=loop
- 或=or
- 执行=do
- 抛出=raise
- 收尾=finally
- 整除=div
- 新=new
- 是=is
- 有=when
- 真=true
- 空=null
- 类=class
- 结束=end
- 设=for
- 跳出=exit
- 跳过=next
- 返回=return
- 递增=step
- 非=not
下载该库
-- [全文完] - Funlang.org