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

  1. ########################################
  2. # if
  3. ########################################
  4. # if expression then cmds
  5. # { elsif expression then cmds } 0..n
  6. # [ else cmds ] 0..1
  7. # end if;
  8. ########################################
  9. if true then
  10. ..?. true; # HIT
  11. end if;
  12. if false then
  13. ..?. false;
  14. else
  15. ..?. true; # HIT
  16. end if;
  17. if false then
  18. ..?. false;
  19. elsif true then
  20. ..?. true; # HIT
  21. else
  22. ..?. "What's wrong with you?";
  23. end if;
  24. ########################################
  25. # 1. Comments start with "#" or "//"
  26. # Comment block: #* ... #
  27. # 2. "true", "false" are keywords
  28. # 3. "?." means output (append extra \r\n)
  29. # "?," means output (append a blank' ')
  30. # "?:" means output (append a TAB )
  31. # "?" means output (without any extra)
  32. ########################################
True True True
下载该演示

1.1.2 case

  1. ########################################
  2. # case
  3. ########################################
  4. # case expression is
  5. # { when value do cmds }+ 1..n
  6. # [ else cmds ] 0..1
  7. # end case;
  8. ########################################
  9. var exp = 1;
  10. case exp is
  11. ..when 1 do
  12. ....?. 1; # HIT
  13. ..when 2 do
  14. ....?. 2;
  15. ..when 3 do
  16. ....?. 3;
  17. ..else
  18. ....?. 'else';
  19. end case;
  20. exp = "Hello";
  21. case exp is
  22. ..when "Good" do
  23. ....?. @ & ' morning!';
  24. ..when "Bad" do
  25. ....?. @ & ' command or file name!';
  26. ..when "Hello" do
  27. ....?. @ & ', world!'; # HIT
  28. ..else
  29. ....?. @ & ' not found!';
  30. end case;
  31. ########################################
  32. # 1. Value in "when" may be anything ([...] or /.../)
  33. # 2. "@" is a built-in variable in "case"
  34. # @ <- expression in "case ... is"
  35. # 3. "&" means string concat
  36. # 4. String quoted with ' or " or `
  37. ########################################
1 Hello, world!
下载该演示

1.2 循环结构: loop

  1. ########################################
  2. # loop
  3. ########################################
  4. # loop
  5. # cmds
  6. # end loop;
  7. ########################################
  8. var i = 1;
  9. loop
  10. ..?. i;
  11. ..exit;
  12. end loop;
  13. loop
  14. ..exit when i > 9;
  15. ..? i;
  16. ..i += 1;
  17. end loop;
  18. ?. '..DONE';
  19. i = 9;
  20. loop
  21. ..i -= 1;
  22. ..exit when i <= 0;
  23. ..next when i mod 2 = 1;
  24. ..? i;
  25. end loop;
  26. ?. '..DONE';
  27. ########################################
  28. # 1. "exit" means exit the loop
  29. # "exit when" means when ... exit ...
  30. # "next" means skip to next loop
  31. # "next when" means when ... next ...
  32. # 2. v += ... means v = v + ...
  33. # v -= ... means v = v - ...
  34. # v *= ... means v = v * ...
  35. # v &= ... means v = v & ...
  36. ########################################
1 123456789..DONE 8642..DONE
下载该演示

1.2.1 while

  1. ########################################
  2. # loop-while
  3. ########################################
  4. # while expression loop
  5. # cmds
  6. # end loop;
  7. ########################################
  8. var i = 1;
  9. while i <= 9 loop
  10. ..? i;
  11. ..i += 1;
  12. end loop;
  13. ?. '..DONE';
  14. i = 9;
  15. while i > 0 do
  16. ..? i;
  17. ..i -= 1;
  18. end do;
  19. ?. '..DONE';
  20. ########################################
  21. # 1. while ... "loop" -> while ... "do"
  22. # end "loop" -> end "do"
  23. ########################################
123456789..DONE 987654321..DONE
下载该演示

1.2.2 for

  1. ########################################
  2. # loop-for
  3. ########################################
  4. # for v = e1 to e2 [step e3] loop
  5. # cmds
  6. # end loop;
  7. ########################################
  8. for i = 1 to 9 loop
  9. ..? i;
  10. end loop;
  11. ?. '..DONE';
  12. for i = 9 to 1 step -1 do
  13. ..? i;
  14. end do;
  15. ?. '..DONE';
  16. ########################################
  17. # 1. for ... "loop" -> for ... "do"
  18. # end "loop" -> end "do"
  19. # 2. v is a built-in variable in loop
  20. ########################################
123456789..DONE 987654321..DONE
下载该演示

1.2.3 for-in

  1. ########################################
  2. # loop-for-in
  3. ########################################
  4. # for v in expression loop
  5. # cmds
  6. # end loop;
  7. ########################################
  8. # for k : v in expression loop
  9. # cmds
  10. # end loop;
  11. ########################################
  12. # for k : v, i in expression loop
  13. # cmds
  14. # end loop;
  15. ########################################
  16. # for v, i in expression loop
  17. # cmds
  18. # end loop;
  19. ########################################
  20. for i in [1, 2, 3, 4, 5] loop
  21. ..? i;
  22. end loop;
  23. ?. '..DONE';
  24. for i in [5, 4, 3, 2, 1] do
  25. ..? i;
  26. end do;
  27. ?. '..DONE';
  28. for k: i in [a: 1, b: 2, c: 3] do
  29. ..?, k;
  30. ..?, i;
  31. end do;
  32. ?. 'DONE';
  33. for k: i, j in [a: 1, b: 2, c: 3] do
  34. ..?, k;
  35. ..?, i;
  36. ..?, j;
  37. end do;
  38. ?. '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

  1. ########################################
  2. # try
  3. ########################################
  4. # try cmds
  5. # [ except cmds ] 0..1
  6. # [ finally cmds ] 0..1
  7. # end try;
  8. ########################################
  9. try
  10. ..? 'try..'; # HIT
  11. except
  12. ..? 'except..';
  13. end try;
  14. ?. 'DONE';
  15. try
  16. ..? 'try..'; # HIT
  17. finally
  18. ..? 'finally..'; # HIT
  19. end try;
  20. ?. 'DONE';
  21. try
  22. ..? 'try..'; # HIT
  23. except
  24. ..? 'except..';
  25. finally
  26. ..? 'finally..'; # HIT
  27. end try;
  28. ?. 'DONE';
  29. try
  30. ..? 'try..'; # HIT
  31. ..? 1 / 0;
  32. ..? '1 / 0';
  33. except
  34. ..? 'except..'; # HIT
  35. ..? @ & '..'; # HIT
  36. finally
  37. ..? 'finally..'; # HIT
  38. end try;
  39. ?. 'DONE';
  40. try
  41. ..? 'try..'; # HIT
  42. ..raise "Stop!";
  43. ..? 'Stop!';
  44. except
  45. ..? 'except..'; # HIT
  46. ..? @ & '..'; # HIT
  47. finally
  48. ..? 'finally..'; # HIT
  49. end try;
  50. ?. 'DONE';
  51. ########################################
  52. # 1. "@" is a built-in variable in "except"
  53. # @ <- exception
  54. # 2. "raise" can throw an exception
  55. # exception can be anything
  56. ########################################
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' 函数来复制对象).
  1. ########################################
  2. # type
  3. ########################################
  4. # Number: [0-9]+(\.[0-9]+)?(e-?[0-9]+)?|0x[0-9a-f]+|0b[01]+
  5. # String: Quoted with ' or " or `
  6. # Time: @String
  7. # Bool: true/false
  8. # Null: null/nil
  9. ########################################
  10. # Number
  11. ?. 123456789;
  12. var n = 1.23456789; ?. n;
  13. n = 0xffffffff; ?. n;
  14. # String
  15. ?. "This is a string.";
  16. var s = 'Hello, string.'; ?. s;
  17. ?. 'it''s me'; // '...''...', "...""...", `...``...`, `...`id`...` (for quine)
  18. # Time
  19. ?. @"2010-04-09 15:35:15";
  20. var t = @'2010-04-09 15:35:15'; ?. t;
  21. # Bool
  22. ?. true;
  23. var b = false; ?. b;
  24. # Null
  25. ?. '[' & 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 有以下类型的运算以及表达式: 数字运算, 字符串运算, 布尔运算等. 布尔表达式经常用在控制结构的条件部分.
  1. ########################################
  2. # calc
  3. ########################################
  4. # Number: + - * / div mod ^
  5. # Bits: << >> (bit not/and/or/xor)
  6. # String: &
  7. # Time: + -
  8. # Bool: not and or xor
  9. # Regex: =~ !~
  10. # Set: in
  11. # Others: = !=(<>) < <= > >=
  12. # Set/Others for any types
  13. ########################################
  14. # precedence (default left association)
  15. ########################################
  16. # () [] .
  17. # ^
  18. # * / div mod
  19. # (bit not) -> right
  20. # (bit and/or/xor) << >>
  21. # + -
  22. # &
  23. # = != <> < <= > >= in =~ !~ -> none
  24. # not -> right
  25. # and
  26. # or xor
  27. ########################################
  28. # short-circuit calculation
  29. ########################################
  30. # and
  31. # or
  32. ########################################
  33. # Number
  34. var n1 = 9;
  35. var n2 = 3.3;
  36. ?. n1 + n2;
  37. ?. n1 - n2;
  38. ?. n1 * n2;
  39. ?. n1 / n2;
  40. ?. n1 div "4"; # Type conversions automatically
  41. ?. n1 mod '4'; # Type conversions automatically
  42. ?. n1 ^ 3; # power
  43. # Bits
  44. n1 = 0x0f;
  45. n2 = 0xf0;
  46. ?. n1 << 4; # shift left
  47. ?. n2 >> 4; # shift right
  48. ?. bit not n1;
  49. ?. n1 bit and n2;
  50. ?. n1 bit or n2;
  51. ?. n1 bit xor n2;
  52. # String
  53. var s1 = 'Hello';
  54. var s2 = ", world!";
  55. ?. s1 & s2 & ' - ' & 10000; # Type conversions automatically
  56. # Time
  57. var t1 = @"2010-04-09 15:35:15";
  58. var t2 = @'2010-03-09 15:35:15';
  59. ?. t1 + 100;
  60. ?. t1 - t2;
  61. # Bool
  62. var b1 = true;
  63. var b2 = false;
  64. ?. not not b1;
  65. ?. not (b1 and b2);
  66. ?. b1 or b2;
  67. ?. b1 xor b2;
  68. # Set
  69. ?. "Hello" in ["Hello", "World"];
  70. # Others - Compare
  71. ?. not 1 = 2;
  72. ?. 1 != 2;
  73. ?. 1 <> 2;
  74. ?. 1 < 2;
  75. ?. 1 <= 2;
  76. ?. not 1 > 2;
  77. ?. not 1 >= 2;
  78. # Null - All null values equal null (number, string, bool, etc.)
  79. ?. null = 0;
  80. ?. null = false;
  81. ?. null = '';
  82. # Short-circuit calculation
  83. ?. true or 1 = 0; # "1 = 0" doesn't need calc
  84. ?. false and 1 = 1; # "1 = 1" doesn't need calc
  85. # Optional
  86. ?. Undefined?;
  87. ?. 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 赋值

变量值只能在一条命令语句中修改, 表达式中是不能修改变量值的.
  1. ########################################
  2. # assign
  3. ########################################
  4. # v = expression;
  5. # v += expression;
  6. # v -= expression;
  7. # v *= expression;
  8. # v &= expression;
  9. ########################################
  10. var a = 1; ?. a = 1;
  11. a += 2; ?. a = 3;
  12. a -= 1; ?. a = 2;
  13. a *= 2; ?. a = 4;
  14. a &= 5; ?. a = '45';
True True True True True
下载该演示

2.5 作用域

变量在块中以关键字 "var" 来声明. 一个模块(文件)或者任意控制结构如 if/elsif/else/case/when/loop 都是块, fun/class 也是块. 变量的作用域规则非常简单, 靠近自己的块就是它的作用域, 即使声明在当前语句的后面也是如此(因此, Fun 语言无需提前声明).
  1. ########################################
  2. # scope
  3. ########################################
  4. var a = 1;
  5. var b = 2;
  6. ?. a = 1;
  7. ?. b = 2;
  8. if true then
  9. ..var a = 2; # new "a"
  10. ..b = 22; # old "b"
  11. ..?. a = 2;
  12. ..?. b = 22;
  13. ..if true then
  14. ....var a = 3; # new "a"
  15. ....b = 33; # old "b"
  16. ....?. a = 3;
  17. ....?. b = 33;
  18. ..end if;
  19. ..?. a = 2;
  20. ..?. b = 33;
  21. end if;
  22. ?. a = 1;
  23. ?. b = 33;
True True True True True True True True True True
下载该演示

3. 函数: 基本的过程化模块化编程

Fun 是一种过程化语言, 支持传统的模块化编程. 函数可以定义在任何块结构中, 其作用域与变量作用域完全相同(实际上, 函数名跟变量完全等价, 在函数式编程的介绍里面会看到).

3.1 函数声明与调用

  1. ########################################
  2. # fun
  3. ########################################
  4. # fun name ( parameters )
  5. # cmds
  6. # end fun;
  7. ########################################
  8. # Define a function named "foo"
  9. fun foo()
  10. ..?. 'Hello, fun!';
  11. end fun;
  12. # Call function "foo"
  13. foo();
  14. # Define a function with parameters
  15. fun max(a, b)
  16. ..if a > b then
  17. ....result = a;
  18. ..else
  19. ....result = b;
  20. ..end if;
  21. end fun;
  22. fun min(a, b)
  23. ..if a < b then
  24. ....return a;
  25. ..else
  26. ....return b;
  27. ..end if;
  28. end fun;
  29. ?. max(1, 9);
  30. ?. max(9, 1);
  31. ?. min(1, 9);
  32. ?. min(9, 1);
  33. ########################################
  34. # 1. "result", "@" are built-in variables in "fun"
  35. # they all be defined as the result value of the fun
  36. # 2. "return" means return the fun
  37. # it can return with/without a value
  38. # 3. "exit" can exit a fun too
  39. ########################################
Hello, fun! 9 9 1 1
下载该演示

3.2 默认参数

  1. ########################################
  2. # fun-default
  3. ########################################
  4. # test define
  5. fun test(a, b, c)
  6. ..# embed inner fun
  7. ..fun echo(name, str)
  8. ....? name & '=[' & str & '] ';
  9. ..end fun;
  10. ..# echo the parameters
  11. ..echo('a', a);
  12. ..echo('b', b);
  13. ..echo('c', c);
  14. ..?. 'DONE';
  15. end fun;
  16. test(1, 2, 3);
  17. test(1, 2); # keep param(s) 'c' as null
  18. test(1); # keep param(s) 'b' and 'c' as null
  19. ########################################
  20. # 1. Default arguments always be set as null
  21. ########################################
a=[1] b=[2] c=[3] DONE a=[1] b=[2] c=[] DONE a=[1] b=[] c=[] DONE
下载该演示

3.3 命名参数

  1. ########################################
  2. # fun-named
  3. ########################################
  4. # { name: value } 0..n
  5. ########################################
  6. # test define
  7. fun test(a, b, c)
  8. ..# embed inner fun
  9. ..fun echo(name, str)
  10. ....? name & '=[' & str & '] ';
  11. ..end fun;
  12. ..# echo the parameters
  13. ..echo('a', a);
  14. ..echo('b', b);
  15. ..echo('c', c);
  16. ..?. 'DONE';
  17. end fun;
  18. test(a: 1, b: 2, c: 3);
  19. test(c: 1, b: 2, a: 3);
  20. test(c: 1, b: 2); # keep param(s) 'a' as null
  21. test(c: 1); # keep param(s) 'b' and 'a' as null
  22. ########################################
  23. # 1. Default arguments always be set as null
  24. ########################################
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" 关键字, 则传递方的变量不被被调用函数修改.
  1. ########################################
  2. # fun-ref
  3. ########################################
  4. fun swap(a, b)
  5. ..var t = a;
  6. ..a = b;
  7. ..b = t;
  8. end fun;
  9. var i = 1;
  10. var j = 9;
  11. ?. i & ' ' & j;
  12. swap(i, j); # Call by value
  13. ?. i & ' ' & j;
  14. swap(var i, var j); # Call by reference
  15. ?. i & ' ' & j;
  16. swap(var i, var j); # Call by reference
  17. ?. i & ' ' & j;
  18. ########################################
  19. # 1. pass "var" arguments to call by reference
  20. ########################################
1 9 1 9 9 1 1 9
下载该演示

3.5 递归调用

  1. ########################################
  2. # fun-recursion
  3. ########################################
  4. for i = 1 to 17 do
  5. ..?. fact(i);
  6. ..fun fact(n)
  7. ....if n > 1 then
  8. ......result = n * fact(n - 1); # call fact recursion
  9. ....else
  10. ......result = 1;
  11. ....end if;
  12. ..end fun;
  13. end do;
1 2 6 24 120 720 5040 40320 362880 3628800 39916800 479001600 6227020800 87178291200 1307674368000 20922789888000 355687428096000
下载该演示

3.6 模块引用

Fun 支持模块复用, 用 "use" 来引用其他模块, 引用时可以重命名.
  1. ########################################
  2. # use
  3. ########################################
  4. # use string;
  5. ########################################
  6. # use string as id;
  7. ########################################
  8. ?. '----Use fun-ref.fun ...';
  9. use 'fun-ref.fun';
  10. ?. '----Used----';
  11. i = 11;
  12. j = 99;
  13. ?. i & ' ' & j;
  14. swap(i, j); # Call by value
  15. ?. i & ' ' & j;
  16. swap(var i, var j); # Call by reference
  17. ?. i & ' ' & j;
  18. swap(var i, var j); # Call by reference
  19. ?. i & ' ' & j;
  20. use 'fun-ref.fun' as lib; # use as alias
  21. i = 111;
  22. j = 999;
  23. ?. i & ' ' & j;
  24. lib.swap(var i, var j); # use via module_alias.name
  25. ?. i & ' ' & j;
  26. ########################################
  27. # 1. The used file will be inited at first (Run Once)
  28. # 2. Can access the IDs for top level of the used file
  29. # Variables and functions/classes and so on
  30. # 3. The latest IDs are valid for same name
  31. # Multiple files be used
  32. # 4. Can re-name the module as a new id, such as
  33. # use "..." as newone;
  34. # ?. newone.test();
  35. # 5. Files Can be used in anywhere
  36. ########################################
----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" 关键字来定义类, 类可以定义在任何地方. 类实例即对象的创建时会调用类的构造函数, 也就是类体里面的代码(不包括成员函数里面的代码).
  1. ########################################
  2. # class
  3. ########################################
  4. # class name ( parameters )
  5. # cmds
  6. # end class;
  7. ########################################
  8. # define a class
  9. class CA()
  10. ..# test for class constructor
  11. ..? 'CA-constructor-starting..';
  12. ..# member variable
  13. ..var name = 'CA';
  14. ..# member function
  15. ..fun showName()
  16. ....?. name;
  17. ..end fun;
  18. ..fun getName()
  19. ....return name;
  20. ..end fun;
  21. ..?. 'DONE';
  22. end class;
  23. # create a class instance (object)
  24. var a = CA();
  25. # use the member variable of object
  26. ?. a.name;
  27. # use the member function of object
  28. a.showName();
  29. ?. a.getName();
CA-constructor-starting..DONE CA CA CA
下载该演示

4.2 继承与多态

Fun 语言只支持单继承. 当一个对象被创建时, 构造函数按照从基类到子类的顺序自动调用. 所有同名成员会自动重载覆盖基类的同名成员. 但程序员可以有选择的使用重载或是当前成员, 凡用 this 前缀调用的成员, 一律是重载, 其他是当前成员.
  1. ########################################
  2. # class-subclass
  3. ########################################
  4. # class name = base ( parameters )
  5. # cmds
  6. # end class;
  7. ########################################
  8. # define a class
  9. class CA()
  10. ..? 'CA-constructor-starting..';
  11. ..var name = 'CA';
  12. ..fun showName()
  13. ....?. name;
  14. ..end fun;
  15. ..fun getName()
  16. ....return name;
  17. ..end fun;
  18. ..?. 'DONE';
  19. end class;
  20. # define a sub-class
  21. class CB = CA()
  22. ..? 'CB-constructor-starting..';
  23. ..name = 'CB';
  24. ..?. 'DONE';
  25. end class;
  26. class CC = CB()
  27. ..? 'CC-constructor-starting..';
  28. ..name = 'CC';
  29. ..fun showName()
  30. ....?. '--CC.showName() .. ' & name & ' .. DONE';
  31. ..end fun;
  32. ..?. 'DONE';
  33. end class;
  34. fun test(o)
  35. ..?. o.name;
  36. ..o.showName();
  37. ..?. o.getName();
  38. end fun;
  39. ?. '--CA--';
  40. test( CA() );
  41. ?. '--CB--';
  42. test( CB() );
  43. ?. '--CC--';
  44. 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

  1. ########################################
  2. # class-base
  3. ########################################
  4. # class name = base ( parameters )
  5. # cmds
  6. # end class;
  7. ########################################
  8. # this.field or this.method()
  9. # base.field or base.method()
  10. ########################################
  11. // base class
  12. class CBas()
  13. ..var field = 'field';
  14. ..fun method()
  15. ....?. field;
  16. ..end fun;
  17. ..fun test()
  18. ....?. field;
  19. ....?. this.field;
  20. ....method(); // call the method in this class
  21. ....this.method(); // call the override method
  22. ..end fun;
  23. end class;
  24. // sub class
  25. class CSub = CBas()
  26. ..fun method()
  27. ....? 'CSub.method()..';
  28. ....base.method(); // call the method in base classes
  29. ..end fun;
  30. end class;
  31. // test ...
  32. var bas = CBas();
  33. var sub = CSub();
  34. ?. '--test--bas--'; ?. bas.field; bas.test();
  35. ?. '--test--sub--'; ?. sub.field; sub.test();
  36. // test ...
  37. bas.field = 'bas';
  38. sub.field = 'sub';
  39. ?. '--test--bas--'; ?. bas.field; bas.test();
  40. ?. '--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 运算符重载

  1. ########################################
  2. # class-operators-override
  3. ########################################
  4. # this['+'] = fun (right) { ... }
  5. # this['-'] = fun (right) { ... }
  6. # ...
  7. ########################################
  8. class Number(me)
  9. ..this['+'] = fun (you) {
  10. ....return me + you;
  11. ..};
  12. ..this['-'] = fun (you) {
  13. ....return me - you;
  14. ..};
  15. ..this['*'] = fun (you) {
  16. ....return me * you;
  17. ..};
  18. ..this['/'] = fun (you) {
  19. ....return me / you;
  20. ..};
  21. ..this['\'] = fun (you) {
  22. ....return me div you;
  23. ..};
  24. ..this['%'] = fun (you) {
  25. ....return me mod you;
  26. ..};
  27. ..this['^'] = fun (you) {
  28. ....return me ^ you;
  29. ..};
  30. ..this['='] = fun (you) {
  31. ....return me = you;
  32. ..};
  33. ..this['!'] = fun (you) {
  34. ....return me <> you;
  35. ..};
  36. ..this['>'] = fun (you) {
  37. ....return me > you;
  38. ..};
  39. ..this['<'] = fun (you) {
  40. ....return me < you;
  41. ..};
  42. end class;
  43. var n = Number(10);
  44. ?. n .+ 2; // .+ means + override version
  45. ?. n .- 3; // .- means - override version
  46. ?. n .* 4; // .* means * override version
  47. ?. n ./ 5; // ./ means / override version
  48. ?. n .\ 6; // .\ means \ override version
  49. ?. n .% 7; // .% means % override version
  50. ?. n .^ 8; // .^ means ^ override version
  51. ?. n .> 9; // .> means > override version
  52. ?. n .= 10; // .= means = override version
  53. ?. n .< 11; // .< means < override version
  54. ?. n .! 12; // .! means ! override version
  55. ########################################
  56. # 1. Currently FUN supports override operators(16):
  57. # + - * / \ % ^ ! = < > & ~ ? | #
  58. # 2. All override operators same precedence
  59. # 3. All override operators are duality operators
  60. # So the functions will have one parameter
  61. # 4. Must use "." append operators to use them
  62. ########################################
12 7 40 2 1 3 100000000 True True True True
下载该演示

4.5 一切都是对象

一切都是对象, 包括数字, 字符串, 列表, 函数, 类等等.
  1. ########################################
  2. # object
  3. ########################################
  4. # number
  5. ?. (1.atan() * 2).sin();
  6. # string
  7. ?. '123'.length();
  8. ?. 'abc'.upper();
  9. ?. 'ABC'.lower();
  10. # set/list
  11. ?. [a: 1, b: 2, c: 3].a;
  12. var s1 = [
  13. ..f1: fun(){
  14. ....?. 'hello, f1';
  15. ..},
  16. ..f2: fun(){
  17. ....?. 'hello, f2';
  18. ..}
  19. ];
  20. s1.f1();
  21. s1.f2();
1 3 ABC abc 1 hello, f1 hello, f2
下载该演示

5. 函数式编程

Fun 是一门函数式编程语言, 支持 first-class 和 higher-order 函数. Fun 也支持匿名函数, 闭包和 currying.

5.1 First-class 和高阶函数

  1. ########################################
  2. # functional
  3. ########################################
  4. fun foo(a)
  5. ..?. 'Hello, ' & a & '!';
  6. end fun;
  7. var f = foo;
  8. f('functional');
  9. fun high(f, a)
  10. ..f(a);
  11. end fun;
  12. var h = high;
  13. h(f, 'functional');
Hello, functional! Hello, functional!
下载该演示

5.2 匿名函数

  1. ########################################
  2. # functional-anonymous
  3. ########################################
  4. # fun ( parameters ) { cmds }
  5. ########################################
  6. # fun ( ) { cmds }
  7. ########################################
  8. # ( ) { cmds }
  9. ########################################
  10. # { cmds }
  11. ########################################
  12. fun If(a, b, c)
  13. ..if a then
  14. ....return b();
  15. ..elsif c <> null then
  16. ....return c();
  17. ..end if;
  18. end fun;
  19. fun Loop(a, b)
  20. ..while a() do
  21. ....b();
  22. ..end do;
  23. end fun;
  24. fun For(init, cond, nex1, code)
  25. ..init();
  26. ..while cond() do
  27. ....code();
  28. ....nex1();
  29. ..end do;
  30. end fun;
  31. fun testIf()
  32. ..If(
  33. ....true,
  34. ....{?.true} # Anonymous function (Lambda calculus)
  35. ..);
  36. ..If(
  37. ....false,
  38. ....{?.false}, # Anonymous function (Lambda calculus)
  39. ....{?.true} # Anonymous function (Lambda calculus)
  40. ..);
  41. end fun;
  42. testIf();
  43. fun testLoop()
  44. ..var i = 0;
  45. ..var s = 0;
  46. ..Loop(
  47. ....{return i < 10}, # Anonymous function (Lambda calculus)
  48. ....{?, i; i += 1} # Anonymous function (Lambda calculus)
  49. ..);
  50. ..?. 'DONE';
  51. ..For(
  52. ....{i = 1; s = 0}, # Anonymous function (Lambda calculus)
  53. ....{@ = i <= 1000}, # Anonymous function (Lambda calculus)
  54. ....{i += 1}, # Anonymous function (Lambda calculus)
  55. ....{s += i} # Anonymous function (Lambda calculus)
  56. ..);
  57. ..?. s;
  58. end fun;
  59. testLoop();
  60. ########################################
  61. # 1. "@" is a built-in variable in "fun"
  62. # @ <- result
  63. # 2. {...} <- (){} <- fun(){}
  64. # with parameters must use
  65. # fun(parameters){} or
  66. # (parameters){}
  67. # 3. "?." means output (append extra \r\n)
  68. # "?," means output (append a blank' ')
  69. # "?:" means output (append a TAB )
  70. # "?" means output (without any extra)
  71. ########################################
True True 0 1 2 3 4 5 6 7 8 9 DONE 500500
下载该演示

5.3 闭包

  1. ########################################
  2. # functional-closure
  3. ########################################
  4. fun counter()
  5. ..var i = 0;
  6. ..return fun(){
  7. ....i += 1;
  8. ....result = i;
  9. ..};
  10. end fun;
  11. var c = counter();
  12. ?. c();
  13. ?. c();
  14. ?. c();
  15. fun mul(bas)
  16. ..return fun(times){
  17. ....return bas * times;
  18. ..};
  19. end fun;
  20. var m = mul(3);
  21. ?. m(4);
  22. ?. m(5);
  23. ?. m(6);
1 2 3 12 15 18
下载该演示

5.4 Currying

  1. ########################################
  2. # functional-currying
  3. ########################################
  4. # fun name ( arguments )
  5. ########################################
  6. fun mul(bas, times)
  7. ..return bas * times;
  8. end fun;
  9. var m = fun mul(3);
  10. ?. m(4);
  11. ?. m(5);
  12. ?. m(6);
12 15 18
下载该演示

5.5 数学式函数

  1. ########################################
  2. # functional-mathematics
  3. ########################################
  4. # var name ( arguments ) = exp;
  5. ########################################
  6. # ( arguments ) -> exp
  7. # ( ) -> exp
  8. # argument -> exp
  9. # -> exp
  10. ########################################
  11. var ifv = (condition, vtrue, vfalse){
  12. ..if condition then
  13. ....return vtrue;
  14. ..else
  15. ....return vfalse;
  16. ..end if;
  17. };
  18. var forto = (start, end1, step1, action){
  19. ..result = 0;
  20. ..for i = start to end1 step step1 do
  21. ....result = action(i, result);
  22. ..end do;
  23. };
  24. var sqrt(n) = n ^ 0.5;
  25. var max(a, b) = ifv(a > b, a, b);
  26. var min(a, b) = ifv(a < b, a, b);
  27. var sqrt2 = n -> n ^ 0.5;
  28. var max2 = (a, b) -> ifv(a > b, a, b);
  29. var min2 = (a, b) -> ifv(a < b, a, b);
  30. var sum(s, e, i) = forto(s, e, i, (i, r) -> r + i);
  31. var sum1(n) = sum(1, n, 1);
  32. var fact(n) = forto(1, n, 1, (i, r) -> ifv(r=0, 1, r) * i);
  33. ?. sqrt(9);
  34. ?. max(1, 2);
  35. ?. min(1, 2);
  36. ?. sqrt2(9);
  37. ?. max2(1, 2);
  38. ?. min2(1, 2);
  39. ?. sum(1, 10000, 1);
  40. ?. sum1(10000);
  41. ?. fact(17);
3 2 1 3 2 1 50005000 50005000 355687428096000
下载该演示

6. 列表: 集合处理

Fun 内置了一个简单的方便的列表, 看起来像是数组, 字典, hash 表等. 类似的名词可以包括: 集合, 列表, 数组, 关联数组, hash, map, 字典等等. 在 Fun 语言里面这些全是同一个东西, 甚至函数, 类, 对象等全是.

6.1 数组

  1. ########################################
  2. # set
  3. ########################################
  4. # [ value, value, value ... ]
  5. ########################################
  6. var list = [0, 1, 2, 3, 4, 5];
  7. ?. 1 in list;
  8. ?. 3 in list;
  9. ?. 5 in list;
  10. ?. not 7 in list;
  11. for i in list do
  12. ..?, i;
  13. end do;
  14. ?. 'DONE';
  15. ?. list[0];
  16. ?. list[1];
  17. ?. list[-1];
  18. ?. list[-2];
  19. list[3] = -3;
  20. list[-1] = -5;
  21. for i in list do
  22. ..?, i;
  23. end do;
  24. ?. 'DONE';
  25. ########################################
  26. # 1. The elements can be anything includes base types and object types
  27. #
  28. # [num: 1, str: "string", time: @'2010-04-23 17:26:22', bool: false]
  29. #
  30. # [[name: 'fun', value: 'function'], [name: 'obj', value: 'object']]
  31. #
  32. # 2. Index of list start from 0 to N-1 and from -N to -1, as below:
  33. #
  34. # var N = list.count();
  35. #
  36. # [ 0 1 2 3 ... N-3 N-2 N-1 ]
  37. # ------------> ++1 --------->
  38. #
  39. # [ 0-N 1-N 2-N 3-N ... -3 -2 -1 ]
  40. # <------------ --1 <---------
  41. #
  42. # !!! Index must be Integer, Don't Use any Float or Double Index !!!
  43. ########################################
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 表, 实际上是同一个东西, 区别在于你有没有给一个元素命名. 全部元素都没名字的看起来像是传统的数组, 全部命名的就像是传统的字典, 而且还可以有混合的. 对照前面的函数命名参数不难发现, 函数参数表实际上也是跟这个一样, 是同一种东西.
  1. ########################################
  2. # set-named
  3. ########################################
  4. # [ name: value, name: value ... ]
  5. ########################################
  6. var list = [red: 0x0000ff, green: 0x00ff00, blue: 0xff0000, 0xffff00, '黄色': 0xffff00, '显示': a -> a & '!', ];
  7. for i in list do
  8. ..?, i;
  9. end do;
  10. ?. 'DONE';
  11. ?, 'red';
  12. ?, list[0];
  13. ?, list['red'];
  14. ?. list.red;
  15. ?, 'green';
  16. ?, list[1];
  17. ?, list['green'];
  18. ?. list.green;
  19. ?, 'blue';
  20. ?, list[2];
  21. ?, list['blue'];
  22. ?. list.blue;
  23. list.yellow = 0x00ffff;
  24. list['white'] = 0xffffff;
  25. list["black"] = 0x000000;
  26. for i in list do
  27. ..?, i;
  28. end do;
  29. ?. 'DONE';
  30. ?. list.'黄色';
  31. ?. 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() 函数. 这在函数里面或者循环里面非常有用.
  1. ########################################
  2. # set-clone
  3. ########################################
  4. # new [...]
  5. ########################################
  6. # s.@clone()
  7. ########################################
  8. var s1 = new [1, 2, 3];
  9. s1.@each((i){?,i}); ?. null;
  10. var s2 = s1.@clone();
  11. s2.@each((i){?,i}); ?. null;
  12. s1[0] = 11;
  13. s2[1] = 22;
  14. s1.@each((i){?,i}); ?. null;
  15. s2.@each((i){?,i}); ?. null;
1 2 3 1 2 3 11 2 3 1 22 3
下载该演示

6.4 有关列表的库

  1. ########################################
  2. # lib-set
  3. ########################################
  4. # built-in (4)
  5. ########################################
  6. # s.@count ()
  7. # s.@each (fun, reverse = false) # fun (val) or (val, key)
  8. # s.@add (v1, v2, ...)
  9. # s.@clone ()
  10. ########################################
  11. var pathSet(set, path, value) = locate(set, path, value, 1);
  12. var pathInc(set, path, value) = locate(set, path, value, 2);
  13. fun locate(set, path, value, mode) // mode: 0-get, 1-set, 2-inc
  14. ..var lp = nil;
  15. ..for p in path do
  16. ....if lp <> nil then
  17. ......if set[lp] = nil then
  18. ........set[lp] = new [];
  19. ......end if;
  20. ......set = set[lp];
  21. ....end if;
  22. ....lp = p;
  23. ..end do;
  24. ..result = set[lp];
  25. ..if mode = 1 then
  26. ....set[lp] = value;
  27. ..elsif mode = 2 then
  28. ....set[lp] += value;
  29. ..end if;
  30. end fun;
  31. fun filter(s, f, n)
  32. ..var ret = n or new [];
  33. ..s.@each((v, k){
  34. ....if f(var v, k) then
  35. ......if k <> nil then
  36. ........ret[k] = v;
  37. ......else
  38. ........ret.@add(v);
  39. ......end if;
  40. ....end if;
  41. ..});
  42. ..result = ret;
  43. end fun;
  44. fun find(s, f)
  45. ..result = nil;
  46. ..for v in s do
  47. ....if f(v) then
  48. ......return v;
  49. ....end if;
  50. ..end do;
  51. end fun;
  52. fun compose(args, a)
  53. ..args.@each((f){
  54. ....a = f(a);
  55. ..}, true);
  56. ..return a;
  57. end fun;
  58. fun map(fn, list)
  59. ..var set = new [];
  60. ..list.@each( v -> set.@add(fn(v)) );
  61. ..result = set;
  62. end fun;
  63. fun fromPairs(list)
  64. ..var set = new [];
  65. ..list.@each( (v){
  66. ....set[v[0]] = v[1];
  67. ..});
  68. ..result = set;
  69. end fun;
  70. fun reducePairs(p, a)
  71. ..a = a or new [];
  72. ..for i = 0 to p.@count() -1 step 2 do
  73. ....a[p[i]] = p[i+1];
  74. ..end do;
  75. ..result = a;
  76. end fun;
  77. fun mapReduce(map, reduce, a)
  78. ..var ret;
  79. ..a.@each( v -> reduce(map(v), var ret) );
  80. ..result = ret;
  81. end fun;
  82. var mapReduceEx(map, reduce, preMap, a) = mapReduce(map, reduce, preMap(a));
  83. fun formats(str, set)
  84. ..result = str.replace(/\{(\w++)\}/g, (m){
  85. ....result = formats(set[m.@(1)], set);
  86. ..});
  87. end fun;
  88. var mergeJson = mergeSet;
  89. fun mergeSet(src, dst, isInc)
  90. ..for k: v in src do
  91. ....if k = nil then
  92. ......dst.@add(v);
  93. ....elsif dst[k] = nil then
  94. ......dst[k] = v;
  95. ....else
  96. ......try
  97. ........if v.@count() > 0 or dst[k].@count() > 0 then
  98. ..........mergeSet(v, dst[k], isInc);
  99. ........else
  100. ..........setRet();
  101. ........end if;
  102. ......except //?. @;
  103. ........setRet();
  104. ......end try;
  105. ....end if;
  106. ....fun setRet()
  107. ......try
  108. ........if isInc then
  109. ..........dst[k] += v * 1;
  110. ........else
  111. ..........dst[k] = v;
  112. ........end if;
  113. ......except
  114. ........dst[k] = v;
  115. ......end try;
  116. ....end fun;
  117. ..end do;
  118. end fun;
  119. # result = s2 - s1
  120. fun diffSet(s1, s2, ret)
  121. ..ret = ret or new [];
  122. ..result = ret;
  123. ..for k: v in s2 do
  124. ....if s1[k] = nil then
  125. ......setRet();
  126. ....else
  127. ......try
  128. ........if s2[k].@count() >= 0 and s1[k].@count() >= 0 then
  129. ..........var d = diffSet(s1[k], s2[k]);
  130. ..........if d then
  131. ............ret[k] = d;
  132. ..........end if;
  133. ........else
  134. ..........setRet();
  135. ........end if;
  136. ......except //?. @;
  137. ........setRet();
  138. ......end try;
  139. ....end if;
  140. ....fun setRet()
  141. ......if v <> s1[k] then
  142. ........if k = nil then
  143. ..........ret.@add(v);
  144. ........else
  145. ..........ret[k] = v;
  146. ........end if;
  147. ......end if;
  148. ....end fun;
  149. ..end do;
  150. end fun;
下载该库
  1. ########################################
  2. # test for lib-set.fun
  3. ########################################
  4. use '..\lib\lib-set.fun';
  5. test();
  6. fun test()
  7. ..?. [1, 2, 3].@count();
  8. ..[1, 2, 3].@each((i){?,i});
  9. ..?. 'DONE';
  10. ..var abc = [a: 1, b: 2, c: 3];
  11. ..abc.@each((i, k){?,k & '=' & i});
  12. ..?. 'DONE';
  13. ..abc.@add(4, 5, 6, g: 7, h: 8, i: 9)
  14. ......@each((i, k){?,k & '=' & i});
  15. ..?. 'DONE';
  16. 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 格式

  1. ########################################
  2. # lib-json
  3. ########################################
  4. # built-in (2)
  5. ########################################
  6. # set.@toJson (format, json) # save set as JSON string
  7. # str.getJson (json = false) # load str as JSON set/list/tree
  8. ########################################
  9. # 1. format param of @toJson()
  10. # default 0, format levels
  11. # join (concat) if format = -1
  12. # 2. json param of @toJson()
  13. # default false, name quoted as "name"
  14. ########################################
  15. fun JSON()
  16. ..fun Parse(s)
  17. ....result = s.getJson(json: true);
  18. ..end fun;
  19. ..fun Stringify(s, level)
  20. ....result = s.@toJson(level, json: true);
  21. ..end fun;
  22. end fun;
下载该库
  1. ########################################
  2. # test for lib-json.fun
  3. ########################################
  4. use '..\lib\lib-json.fun';
  5. test();
  6. fun test()
  7. ..var s1 = '[1, 2, 3]'.getJson();
  8. ..s1.@each((i){?,i});
  9. ..?. '';
  10. ..?. s1.@toJson();
  11. ..var s2 = "[{key: str, val: 'this is a string.'},
  12. {key: num, val: 123456789}]".getJson();
  13. ..s2.@each(
  14. ....(i){
  15. ......i.@each(
  16. ........(v, k){
  17. ..........?, k & ': ' & v;
  18. ........}
  19. ......);
  20. ......?. null;
  21. ....}
  22. ..);
  23. ..?. 'format: 0';
  24. ..?. s2.@toJson();
  25. ..?. 'format: 1 level';
  26. ..?. s2.@toJson(format: 1);
  27. ..?. 'format: 2 levels';
  28. ..?. s2.@toJson(format: 2);
  29. 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)

  1. ########################################
  2. # lib-regex
  3. ########################################
  4. # built-in (3)
  5. ########################################
  6. # match:
  7. # str.match(str) # match only in string form
  8. #
  9. # str.match(reg) # match in regex pattern
  10. # reg.match(str) # match in regex pattern
  11. # str.match(reg, action) # match in regex pattern
  12. # reg.match(str, action) # match in regex pattern
  13. #
  14. # replace:
  15. # str.replace(str, newstr) # replace all in string form
  16. #
  17. # str.replace(reg, newone) # replace in regex pattern
  18. # reg.replace(str, newone) # replace in regex pattern
  19. #
  20. # toRegex:
  21. # str.toRegex(options) # options: g, i, m, s, u, x
  22. ########################################
  23. # 1. str: string
  24. # reg: regex
  25. # 2. if 'g' in regex option, match() return a list of matched string
  26. # if action exists, the action will be performed with a match
  27. # object argument for every match, and return string concated
  28. # from the return value of the action
  29. # or, match() return a match object with all matched groups
  30. # (matched string is 0 of the groups)
  31. # if action exists, the action will be performed with the match
  32. # object one time, and return string from the return value of
  33. # the action
  34. # 3. if newone is string, replace with the string one time or all
  35. # (according to 'g')
  36. # or if newone is action (function), replace with the return value
  37. # of the action
  38. # 4. options:
  39. # g - global, match or replace all
  40. # i - ignore case, case insensitive
  41. # m - multiple lines, ^ and $ match start or end of any line
  42. # s - single line, dot(.) match any character, even newline(\n)
  43. # u - UTF8
  44. # x - extended, allow regex to contain extra whitespace and comments
  45. # e.g.: '\d+'.toRegex('g')
  46. ########################################
  47. # return left string, the right argument must be var right, e.g.:
  48. # var right = '';
  49. # var left = splitonce(/\./, 'a.b', var right);
  50. # // Now, left = a, right = b
  51. var splitonce(re, str, right) = re.match(str, (m){
  52. ....@ = m.missed();
  53. ....right = m.rest();
  54. ..});
  55. # return a list
  56. var split = (re, str){
  57. ......result = new [];
  58. ......var m = re.match(str);
  59. ......while m.@@() <> nil loop
  60. ........result.@add(m.missed());
  61. ........m.match();
  62. ......end loop;
  63. ......result.@add(m.missed());
  64. };
下载该库
  1. ########################################
  2. # test for lib-regex.fun
  3. ########################################
  4. use '..\lib\lib-regex.fun';
  5. test();
  6. fun test()
  7. ..# str.match(str), return bool
  8. ..?, 'abcd123efg' =~ '123';
  9. ..?, 'abcd123efg' !~ '1234';
  10. ..?, 'abcd123efg' .match( '123' );
  11. ..?. not 'abcd123efg' .match( '1234' );
  12. ..# str.match(reg), reg.match(str), return bool
  13. ..?, not not 'abcd123efg' =~ /123/; # Convert to bool
  14. ..?, /1234/ !~ 'abcd123efg';
  15. ..?, not not 'abcd123efg' .match( /123/ );
  16. ..?. not '1234'.toRegex().match( 'abcd123efg' );
  17. ..# g, return list of matched string
  18. ..'abcd123efg'.match(/\d/g).@each((m){? '[' & m & ']'});
  19. ..?. null;
  20. ..# not g, return match object
  21. ..?. 'abcd123efg'.match(/\d+/).value();
  22. ..# str.match(reg, action), reg.match(str, action)
  23. ..# return string concated from return value of action
  24. ..?. 'abcd123efg'.match(/\d/g, (m){@= '[' & m.value() & ']'});
  25. ..?. 'abcd123efg'.match(/\d/i, (m){@= '[' & m.value() & ']'});
  26. ..# str.replace(str, newstr)
  27. ..?. 'abcd123efg'.replace('123', '[123]');
  28. ..# str.replace(reg, newstr), reg.replace(str, newstr)
  29. ..?. 'abcd123efg'.replace(/\d/g, '[$0]');
  30. ..# str.replace(reg, action), reg.replace(str, action)
  31. ..?. 'abcd123efg'.replace(/\d/g, (m){@= '[' & m.value() * 3 & ']'});
  32. ..var right = '';
  33. ..var left = splitonce(/\./, 'a.b', var right);
  34. ..?. 'left: [$left], right: [$right]'.eval();
  35. ..split('a.b.c.d', /\./).@each((m){?, '[' & m & ']'});
  36. ..?. null;
  37. 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 函数都有一个匹配对象参数.
  1. ########################################
  2. # lib-match (match object)
  3. ########################################
  4. # built-in (6)
  5. ########################################
  6. # m.match() # perform next match, return success or not
  7. #
  8. # m.missed() # return string missed (Left string of matched)
  9. # m.value() # return string matched
  10. # m.value(substi) # return string substitute
  11. # m.@@() # return string matched
  12. # m.@@(substi) # return string substitute
  13. # m.rest() # return string rest (All right string)
  14. #
  15. # m.gcount() # return group count
  16. #
  17. # m.groups(num) # return group by index
  18. # m.groups(str) # return group by name
  19. # m.@(num) # group by index
  20. # m.@(str) # group by name
  21. ########################################
下载该库
  1. ########################################
  2. # test for lib-match.fun
  3. ########################################
  4. use '..\lib\lib-match.fun';
  5. test();
  6. fun test()
  7. ..var m = 'a.b.c.d' =~ /\./;
  8. ..loop
  9. ....print(m.missed(), 'missed');
  10. ....print(m.value(), 'value');
  11. ....print(m.@@(), '@@');
  12. ....print(m.rest(), 'rest');
  13. ....?. null;
  14. ....exit when not m.match();
  15. ..end loop;
  16. ..print(m.missed(), 'missed');
  17. ..?. null;
  18. ..m = 'a.b.c' =~ /^(?P<first>\w)\.(\w)\.(\w)$/;
  19. ..print(m.gcount(), 'Count');
  20. ..print(m.groups('first'), 'first');
  21. ..?. null;
  22. ..for i = 0 to m.gcount() - 1 do
  23. ....print(m.@(i), i);
  24. ..end do;
  25. ..?. null;
  26. ..fun print(str, name)
  27. ....?, '$name: [$str]'.eval();
  28. ..end fun;
  29. 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]
下载该演示
  1. //Outer brackets: \((\d++(?:\.\d++)?|(?R))(?:[+\-*/](?1))++\)
  2. // Simplify: \((\d+(\.\d+)?|(?R))([+\-*/](?1))+\)
  3. //Inner brackets: ((\d++(?:\.\d++)?|(?3))(?:[+\-*/](?2))++)|(\((?1)\))
  4. // Simplify: ((\d+(\.\d+)?|(?5))([+\-*/](?2))+)|(\((?1)\))
  5. var re = $'
  6. (
  7. (\d++(?:\.\d++)? | (?3))
  8. (?: [+\-*/]
  9. (?2)
  10. )++
  11. )
  12. |
  13. ( \( (?1) \) )
  14. 'x;
  15. ?. 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 数学库

  1. ########################################
  2. # lib-base
  3. ########################################
  4. fun ifval (condition, vtrue, vfalse)
  5. ..if condition then
  6. ....return vtrue;
  7. ..else
  8. ....return vfalse;
  9. ..end if;
  10. end fun;
  11. var ifv = ifval;
  12. var ifb(c) = ifv(c, true, false);
  13. var iff(c, t, f) = ifv(c(), t, f);
  14. var iffa(c, t, f) = ifa(c(), t, f);
  15. fun ifa (condition, atrue, afalse)
  16. ..if condition then
  17. ....return atrue ();
  18. ..else
  19. ....return afalse();
  20. ..end if;
  21. end fun;
  22. fun forloop (start, end1, step1, action, set)
  23. ..result = set;
  24. ..for i = start to end1 step step1 do
  25. ....result = action(i, result) or result;
  26. ..end do;
  27. end fun;
  28. var forto = forloop;
  29. var forE(num, action, set) = forto(1, num, 1, action, set);
  30. var filter = (start, end1, step1, cond, action){
  31. ..result = [];
  32. ..forto(start, end1, step1, (i, ret){
  33. ....if cond(i, ret) then
  34. ......action(i, ret);
  35. ....end if;
  36. ....result = ret;
  37. ..}, result);
  38. };
  39. var filter1(s, e, c, a) = filter(s, e, 1, c, a);
  40. fun foreach (set1, action)
  41. ..for k: v in set1 do
  42. ....action(v, k);
  43. ..end do;
  44. end fun;
  45. var forin = foreach;
下载该库
  1. ########################################
  2. # lib-math
  3. ########################################
  4. # built-in (6)
  5. ########################################
  6. # a.exp () # e ^ a
  7. # a.log () # LogE(a)
  8. # a.sin ()
  9. # a.cos ()
  10. # a.atan ()
  11. # a.random () # 1.random(), 0.random(), a.random(), -1.random(seed = 0)
  12. ########################################
  13. #use 'lib-base.fun';
  14. var pow(a, b) = a ^ b;
  15. var sqrt(a) = a ^ 0.5;
  16. var exp(a) = a.exp();
  17. var log(a) = a.log();
  18. var log2(a) = a.log() / 2.log();
  19. var log10(a) = a.log() / 10.log();
  20. var sin(a) = a.sin();
  21. var cos(a) = a.cos();
  22. var tan(a) = a.sin() / a.cos();
  23. var atan(a) = a.atan();
  24. var asin(a) = atan(a / sqrt(1 - a ^ 2));
  25. var acos(a) = atan(a / sqrt(1 - a ^ 2) * -1) + 2 * atan(1);
  26. var pi() = 1.atan() * 4;
  27. var e() = 1.exp();
  28. var phi() = (5^0.5+1)/2;
  29. #var max(a, b) = ifv(a > b, a, b);
  30. #var min(a, b) = ifv(a < b, a, b);
  31. #var abs(a) = ifv(a < 0, a * -1, a);
  32. var max(a, b) = a > b and a or b;
  33. var min(a, b) = a < b and a or b;
  34. var abs(a) = a < 0 and a * -1 or a;
  35. //var round(a) = a div 1;
  36. var round(a, b) = a * 10^b div 1 / 10^b;
  37. var floor(a) = a div 1 > a and a div 1 - 1 or a div 1;
  38. var ceil(a) = a div 1 < a and a div 1 + 1 or a div 1;
  39. var gcd(x, y) = y and gcd(y, x mod y) or x;
  40. var lcm(x, y) = x * y / gcd(x, y);
  41. var random() = 1.random(); # return x in 0..1
  42. var randomize() = 0.random();
  43. var randomint(a) = a.random(); # return x in 0..a
下载该库
  1. ########################################
  2. # test for lib-math.fun
  3. ########################################
  4. use '..\lib\lib-math.fun';
  5. test();
  6. fun test()
  7. ..?, 8 = pow(2, 3);
  8. ..?, 2 = sqrt(4);
  9. ..?, e() = exp(1);
  10. ..?, 2 = log(exp(2));
  11. ..?, 3 = log2(pow(2, 3));
  12. ..?. 4 = log10(pow(10, 4));
  13. ..?, 0.000001 > abs(1 - sin(pi() / 6) * 2);
  14. ..?, 0.000001 > abs(1 - cos(pi() / 3) * 2);
  15. ..?, 0.000001 > abs(1 - tan(pi() / 4));
  16. ..?, 0.000001 > abs(pi() - atan(sqrt(3)) * 3);
  17. ..?, 0.000001 > abs(pi() - asin(sqrt(3) / 2) * 3);
  18. ..?. 0.000001 > abs(pi() - acos(sqrt(3) / 2) * 6);
  19. ..?, pi();
  20. ..?. e();
  21. ..?, 9 = max(1, 9);
  22. ..?, 1 = min(1, 9);
  23. ..?, 1 = abs(-1);
  24. ..?, 1 = round(1.4);
  25. ..?, 1 = round(1.4999);
  26. ..?. 2 = round(1.5);
  27. ..randomize();
  28. ..?, random() < 1;
  29. ..?, random() < 1;
  30. ..?, random() < 1;
  31. ..?, randomint(100) < 100;
  32. ..?, randomint(100) < 100;
  33. ..?. randomint(100) < 100;
  34. 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 字符串库

  1. ########################################
  2. # lib-string
  3. ########################################
  4. # built-in (9)
  5. ########################################
  6. # a.length ()
  7. # a.lower ()
  8. # a.upper ()
  9. # a.subpos (sub)
  10. # a.substr (pos, len) # Default pos=0, len=MAX, can be negative
  11. # a.move (ptr) # ptr: int, copy to ptr
  12. # a.x (n) # Replicate n times, or reverse (n = -1)
  13. # # sort (n = -2)
  14. # a.escape () # \ abtvrnf'"?/\ \x HH \u HHHH
  15. # a.format (A1, A2, ... An) # %s
  16. # a.eval () # $id
  17. ########################################
  18. # 1. a.escape()
  19. # \a \b \t \v \r \n \f
  20. # \' \" \? \/ \\
  21. # \xHH \uHHHH
  22. ########################################
下载该库
  1. ########################################
  2. # test for lib-string.fun
  3. ########################################
  4. use '..\lib\lib-string.fun';
  5. test();
  6. fun test()
  7. ..var a = 'Www.FunLang.Org';
  8. ..?. a.length();
  9. ..?. a.lower();
  10. ..?. a.upper();
  11. ..var b = a.lower();
  12. ..?. b.subpos('fun');
  13. ..?. b.substr();
  14. ..?. b.substr(4);
  15. ..?. b.substr(4, 7);
  16. ..?. b.substr(len: 3);
  17. ..?. b.substr(4, -8);
  18. ..?. b.substr(-3);
  19. ..?. a.substr(4, 7).x(3);
  20. ..var c = '[Hello\t\\\r\n\?\x40]';
  21. ..?. c;
  22. ..?. c.escape();
  23. ..var d = 'Error: %s at %s/%s.';
  24. ..?. d;
  25. ..?. d.format('"a" not found', 10, 3);
  26. ..var name = 'David';
  27. ..var e = 'Hello, $name.';
  28. ..?. e;
  29. ..?. e.eval();
  30. 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 时间和日期

  1. ########################################
  2. # lib-time
  3. ########################################
  4. # built-in (2)
  5. ########################################
  6. # a.time () # 0.time(), a.time()
  7. # a.format() # yyyy-mm-dd hh:nn:ss:zzz
  8. ########################################
  9. var date() = 1.time(); # return date & time
  10. var time() = 0.time(); # return time
  11. var ms = 24 * 60 * 60 * 1000;
  12. class tick()
  13. ..var t = time();
  14. ..var get = {
  15. ....result = (time() - t) * ms div 1;
  16. ....t = time();
  17. ..};
  18. ..var getStr = {
  19. ....result = get();
  20. ....if result < 100 then
  21. ......result = result div 1 & ' milliseconds';
  22. ....elsif result < 1000 * 60 then
  23. ......result = result div 100 / 10 & ' seconds';
  24. ....elsif result < 1000 * 60 * 60 then
  25. ......result = result / 1000 div 6 / 10 & ' minutes';
  26. ....else
  27. ......result = result / 60000 div 6 / 10 & ' hours';
  28. ....end if;
  29. ..};
  30. ..var show = (s, ms){
  31. ....if ms = 0 then ms = 1; end if;
  32. ....result = s & ': ' & get() / ms;
  33. ..};
  34. end class;
  35. fun diffDate(y, m, d, default, diff, now)
  36. ..now = now or 1.time();
  37. ..result = default;
  38. ..try
  39. ....var mm = 'mm';
  40. ....var dd = 'dd';
  41. ....if diff in ['m', 'y'] then
  42. ......dd = 15;
  43. ......d = 15;
  44. ....end if;
  45. ....if diff = 'y' then
  46. ......mm = 7;
  47. ......m = 7;
  48. ....end if;
  49. ....result = now.format('yyyy-$mm-$dd'.eval()).toTime() - '$y-$m-$d'.eval().replace(/[^\d\-]++/g, '').toTime();
  50. ....if diff = 'm' then
  51. ......result = result / 30.436875 div 1;
  52. ....elsif diff = 'y' then
  53. ......result = result / 365.2425 div 1;
  54. ....end if;
  55. ..except
  56. ..end try;
  57. end fun;
下载该库
  1. ########################################
  2. # test for lib-time.fun
  3. ########################################
  4. use '..\lib\lib-time.fun';
  5. test();
  6. fun test()
  7. ..?. date();
  8. ..?. time();
  9. ..var t = tick();
  10. ..var s = 0;
  11. ..for i = 1 to 1000000 do
  12. ....s += i;
  13. ..end do;
  14. ..?, s;
  15. ..?. t.get();
  16. end fun;
2023-8-26 14:42:11 14:42:11 500000500000 156
下载该演示

8.4 文件操作

  1. ########################################
  2. # lib-file
  3. ########################################
  4. # built-in (8)
  5. ########################################
  6. # f.load ()
  7. # f.save (str, cp = 0, append = false) # cp 10056 - utf8 without bom
  8. # f.find (sub = false) # find directory if f endswith '\'
  9. # f.copy (f2, f3, ...)
  10. # f.move (f2) # delete f if f2 = null
  11. # f.time (flag) # flag: 0-CreationTime, 1-LastWriteTime
  12. # f.size ()
  13. # f.hash (mode) # mode: 0-MD5, 1-SHA1
  14. ########################################
下载该库
  1. ########################################
  2. # test for lib-file.fun
  3. ########################################
  4. use '..\lib\lib-file.fun';
  5. test();
  6. fun test()
  7. ..var f1 = 'c:\temp\admin\a.tmp';
  8. ..var f2 = 'c:\temp\admin\b.tmp';
  9. ..var f3 = 'c:\temp\admin\c.tmp';
  10. ..var fn = 'c:\temp\admin\?.tmp';
  11. ..f1.save('Hello, FUN.');
  12. ..?. f1.load();
  13. ..f1.copy(f2, f3);
  14. ..?. f2.load();
  15. ..?. f3.load();
  16. ..use '..\lib\lib-base.fun';
  17. ..foreach(fn.find(), (f){?.f});
  18. ..f1.move();
  19. ..f2.move();
  20. ..f3.move();
  21. ..foreach(fn.find(), (f){?.f});
  22. 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

  1. ########################################
  2. # lib-winapi
  3. ########################################
  4. # built-in (2)
  5. ########################################
  6. # f.getapi(name, type)
  7. ########################################
  8. # f.@toCallback(nil, type, ptr)
  9. # f.@toCallback(obj, type, ptr)
  10. ########################################
  11. # 1. f.getapi(name, type)
  12. # f: file name (.dll)
  13. # name: proc name or address
  14. # type: xxx...:x
  15. # n(umber) i(nt) l(ong)
  16. # s(tring) w(idestr) a(nsistr) r(awstr)
  17. # p(ointer) v(oid) c(allback)
  18. # 2. how to call?
  19. # method.call() or method()
  20. #
  21. # e.g.:
  22. #
  23. # # get API
  24. # var msgbox = 'user32'.getapi('MessageBox', 'issi:i');
  25. #
  26. # # call via method.call()
  27. # msgbox.call(0, 'Hello, world!', 'Welcome...', 1);
  28. #
  29. # # or call via method()
  30. # msgbox(0, 'Hello, world!', 'Welcome...', 1);
  31. # 3. f.@toCallback(obj, type, ptr)
  32. # f # fun (function)
  33. # obj # object
  34. # type: xxx...:x # W - BSTR (OleString)
  35. # ptr: true or false # default false
  36. ########################################
下载该库
  1. ########################################
  2. # test for lib-winapi.fun
  3. ########################################
  4. use '..\lib\lib-winapi.fun';
  5. test();
  6. fun test()
  7. ..# constants
  8. ..var WM_SETTEXT = 12;
  9. ..var user32 = 'user32';
  10. ..# get APIs
  11. ..var findwin = user32.getapi('FindWindow', 'ss:i');
  12. ..var sendmsg = user32.getapi('SendMessage', 'iiip:i');
  13. ..var gettext = user32.getapi('GetWindowText', 'ipi:i');
  14. ..# settxt call sendmsg() - WM_SETTEXT
  15. ..var settxt(h, t) = sendmsg(h, WM_SETTEXT, 0, t);
  16. ..# gettxt call gettext()
  17. ..var gettxt = (h){
  18. ....result = ' '.x(256);
  19. ....var len = gettext(h, var result, 255);
  20. ....result = result.substr(len: len);
  21. ..};
  22. ..# call findwin via findwin.call()
  23. ..var handle = findwin.call('Shell_TrayWnd', '');
  24. ..# call settxt
  25. ..settxt(handle, 'New text.');
  26. ..# call gettxt
  27. ..?. '[' & gettxt(handle) & ']';
  28. ..# call settxt
  29. ..settxt(handle, '');
  30. ..# call gettxt
  31. ..?. '[' & gettxt(handle) & ']';
  32. end fun;
[New text.] []
下载该演示

8.6 Windows COM

  1. ########################################
  2. # lib-winole
  3. ########################################
  4. # built-in (2)
  5. ########################################
  6. # c.newobj(get = false)
  7. ########################################
  8. # f.@toEvent()
  9. # f.@toEvent(obj)
  10. # f.@toEvent(obj, Source, EventID, DispIDs)
  11. ########################################
  12. # 1. c.newobj(get = false)
  13. # c: class name or id
  14. # get: get an existing COM object
  15. # 2. Call method of ActiveX Object
  16. # obj.Method()
  17. # 3. Property get - @Property
  18. # x = obj.Property # or
  19. # x = obj.@Property() # or
  20. # x = obj.@Property(...) # for Property with params
  21. # 4. Property set - @@Property
  22. # obj.Property = x # or
  23. # obj.@@Property(x) # or
  24. # obj.@@Property(..., x) # for Property with params
  25. # 5. f.@toEvent()
  26. # f # fun (function)
  27. # obj # object
  28. # Source # Windows COM Object
  29. # EventID # IID
  30. # DispIDs # DispID(s)
  31. ########################################
下载该库
  1. ########################################
  2. # test for lib-winole.fun
  3. ########################################
  4. use '..\lib\lib-winole.fun';
  5. use '..\lib\lib-base.fun';
  6. test();
  7. fun test()
  8. ..var f1 = 'c:\temp\admin\1.tmp';
  9. ..var f2 = 'c:\temp\admin\2.tmp';
  10. ..var fn = 'c:\temp\admin\?.tmp';
  11. ..# Create ActiveX Object
  12. ..var sh = 'Wscript.Shell'.newobj();
  13. ..f1.save('Windows COM');
  14. ..# Call Method of COM Object
  15. ..sh.Run('cmd.exe /Ccopy %s %s'.format(f1, f2), 0, true);
  16. ..?. f2.load();
  17. ..foreach(fn.find(), (f){?.f; f.move()});
  18. ..var regex = 'VBScript.RegExp'.newobj();
  19. ..regex.Pattern = '^\d+$'; # Property set, or:
  20. ............................# regex.@@Pattern('^\d+$');
  21. ..?. regex.Pattern; # Property get, or:
  22. ............................# ?. regex.@Pattern();
  23. ..?. regex.Test('123'); # Call method
  24. ..?. regex.Test('abc');
  25. end fun;
Windows COM c:\temp\admin\1.tmp c:\temp\admin\2.tmp ^\d+$ True False
下载该演示

8.7 类型转换

  1. ########################################
  2. # lib-type
  3. ########################################
  4. # built-in (5)
  5. ########################################
  6. # a.toStr(index) # index: default 0, for array; -2: Unicode
  7. # a.toNum(ptr) #1-int, 2-float, 3-double, -1:ptr
  8. # a.toTime()
  9. # a.toByte(pos) # default 0
  10. # a.toChar()
  11. # a.fromByte(pos, byte)
  12. ########################################
下载该库
  1. ########################################
  2. # test for lib-type.fun
  3. ########################################
  4. use '..\lib\lib-type.fun';
  5. test();
  6. fun test()
  7. ..?. 123.toStr() & 456.toStr(); # Auto conversion, same to 123 & 456
  8. ..?. '123'.toNum() * 2; # Auto conversion, same to '123' * 2
  9. ..?. '2010-05-12 15:53:59'.toTime() + 100;
  10. ..?. 'a'.toByte();
  11. ..?. 0x41.toChar();
  12. ..if [] then # Auto convert to false
  13. ....?. '[]';
  14. ..else
  15. ....?. 'not []'; # HIT
  16. ..end if;
  17. ..if [1, 2, 3] then # Auto convert to true
  18. ....?. '[1, 2, 3]'; # HIT
  19. ..else
  20. ....?. 'not [1, 2, 3]';
  21. ..end if;
  22. ..if 'true' or 'yes' or 'NOT_BLANK' then # true <- true, yes, or other NOT BLANK string
  23. ....?. 'true or yes or NOT_BLANK';
  24. ..elsif 'false' or 'no' or '' then # false <- false, no, or BLANK
  25. ....?. 'false or no or BLANK';
  26. ..end if;
  27. end fun;
123456 246 2010-8-20 15:53:59 97 A not [] [1, 2, 3] true or yes or NOT_BLANK
下载该演示

8.8 动态脚本

  1. ########################################
  2. # lib-dyns
  3. ########################################
  4. # built-in (1)
  5. ########################################
  6. # a.compile(inline = false) # file or string
  7. ########################################
  8. # a: file or string
  9. # inline: compile inline to access the current scope
  10. ########################################
下载该库
  1. ########################################
  2. # test for lib-dyns.fun
  3. ########################################
  4. use '..\lib\lib-dyns.fun';
  5. test();
  6. fun test()
  7. ..// compile a file
  8. ..var a = 'lib-file-test.fun'.compile();
  9. ..a(); // execute lib-file-test.fun
  10. ..a.test(); // call test() in lib-file-test.fun
  11. ..// compile a string
  12. ..var b = '?. 1 + 2;'.compile();
  13. ..b();
  14. ..// compile a string inline
  15. ..var c = 'b();'.compile(inline: true);
  16. ..c(); // call b() in the current scope
  17. 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
下载该演示
  1. var s = `var s = `$s`; ?. s.eval();`; ?. s.eval();
var s = `var s = `$s`; ?. s.eval();`; ?. s.eval();
下载该演示

9. 附录

-

9.1 演示

  1. #*======================================
  2. ....FFFFFFFF UU UU NN NN
  3. ....FF UU UU NNN NN
  4. ....FFFFFFF UU UU NN N NN
  5. ....FF UU UU NN N NN
  6. ....FF UU UU NN NNN
  7. ....FF UUUUUU NN NN
  8. ##======================================
  9. var out = output();
  10. class output()
  11. ..var head = (s){?. s & '.'.x(20-s.length())};
  12. ..var body = (s){?, ' '; ?. s};
  13. ..fun close()
  14. ....head('end');
  15. ....? '\r\n'.escape();
  16. ..end fun;
  17. end class;
  18. var idx;
  19. fun closure(o)
  20. ..var i = 0;
  21. ..return {
  22. ....o.body('index $i'.eval());
  23. ....result = i;
  24. ....i += 1;
  25. ..};
  26. end fun;
  27. fun test(n, f)
  28. ..out.head(n);
  29. ..idx = closure(out);
  30. ..f();
  31. ..out.close();
  32. end fun;
  33. test('if', {
  34. ..if idx() > idx() and idx() <= idx() then # short-circuit
  35. ....out.body('wrong');
  36. ..elsif idx() < idx() or idx() >= idx() then # short-circuit
  37. ....out.body('right');
  38. ..elsif idx() = idx() xor idx() <> idx() then
  39. ....out.body('error');
  40. ..else
  41. ....out.body('error');
  42. ..end if;
  43. });
  44. test('case', {
  45. ..case idx() is # @ <- idx()
  46. ....when idx() do
  47. ......out.body('wrong x()');
  48. ....when [idx(), idx()] do // or when new ...
  49. ......out.body('wrong [x]');
  50. ....when '^(%s)$'.format(idx()).toRegex() do
  51. ......out.body('wrong /x/');
  52. ....when '^($@)$'.eval().toRegex() do
  53. ......out.body('right /x/');
  54. ....when idx() do
  55. ......out.body('error');
  56. ....else
  57. ......out.body('error');
  58. ..end case;
  59. });
  60. test('loop', {
  61. ..loop
  62. ....exit when idx() < idx();
  63. ..end loop;
  64. ..for i = idx() to idx() step idx() loop
  65. ....out.body((i = 2) & ' - ' & i);
  66. ..end loop;
  67. ..for k: i in [a: idx(), b: idx(), c: idx()] do // or in new ...
  68. ....out.body('$k: $i'.eval());
  69. ..end do;
  70. ..while idx() < idx() do
  71. ....next when idx() mod 2 = 0;
  72. ....exit when idx() < idx();
  73. ..end do;
  74. ..out.body(idx() = 16);
  75. });
  76. test('try', {
  77. ..try
  78. ....var error() = 1 / 0;
  79. ....idx(); error(); idx();
  80. ..except # @ <- exception
  81. ....out.body('$@ at $@@()'.eval()); # eval $@@ as the last error
  82. ..finally
  83. ....out.body('final'.x(-1)); # reverse: a.x(-1)
  84. ..end try;
  85. });
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 无聊的试验: 汉语中文编程

  1. #===========================================================
  2. #
  3. # 测试中文编程
  4. #
  5. # 测试方法: funu.exe <本文件> -key:key_cn.ini
  6. #
  7. #===========================================================
  8. 如果 真 则
  9. ..?.; # 中
  10. 结束 如果;
  11. 如果 假 则
  12. ..?.;
  13. 再如 真 则
  14. ..?.; # 中
  15. 否则
  16. ..?. '肯定是哪里出错了!';
  17. 结束 如果;
  18. 变量 甲 = 1;
  19. 当 甲 是
  20. ..1 执行
  21. ....?. 1; # 中
  22. ..2 执行
  23. ....?. 2;
  24. ..3 执行
  25. ....?. 3;
  26. ..否则
  27. ....?. '否则';
  28. 结束 当;
  29. = '你好';
  30. 当 甲 是
  31. ..'好' 执行
  32. ....?. '很好很强大!';
  33. ..'坏' 执行
  34. ....?. '很黄很暴力!';
  35. ..'你好' 执行
  36. ....?. @ & ', 世界!'; # 中
  37. ..否则
  38. ....?. @ & '在哪里? 很傻很天真!';
  39. 结束 当;
  40. = 1;
  41. 循环
  42. ..?.;
  43. ..跳出;
  44. 结束 循环;
  45. 循环
  46. ..跳出 有 甲 > 9;
  47. ..?;
  48. ..+= 1;
  49. 结束 循环;
  50. ?. '..搞定';
  51. = 9;
  52. 循环
  53. ..-= 1;
  54. ..跳出 有 甲 <= 0;
  55. ..跳过 有 甲 取余 2 = 1;
  56. ..?;
  57. 结束 循环;
  58. ?. '..搞定';
  59. = 1;
  60. 以 甲 <= 9 循环
  61. ..?;
  62. ..+= 1;
  63. 结束 循环;
  64. ?. '..搞定';
  65. = 9;
  66. 以 甲 > 0 执行
  67. ..?;
  68. ..-= 1;
  69. 结束 执行;
  70. ?. '..搞定';
  71. 设 甲 = 19 循环
  72. ..?;
  73. 结束 循环;
  74. ?. '..搞定';
  75. 设 甲 = 91 递增 -1 执行
  76. ..?;
  77. 结束 执行;
  78. ?. '..搞定';
  79. 设 甲 属于 [1, 2, 3, 4, 5] 循环
  80. ..?;
  81. 结束 循环;
  82. ?. '..搞定';
  83. 设 甲 属于 [5, 4, 3, 2, 1] 执行
  84. ..?;
  85. 结束 执行;
  86. ?. '..搞定';
  87. 尝试
  88. ..? '尝试..'; # 中
  89. 出错
  90. ..? '出错..';
  91. 结束 尝试;
  92. ?. '搞定';
  93. 尝试
  94. ..? '尝试..'; # 中
  95. 收尾
  96. ..? '收尾..'; # 中
  97. 结束 尝试;
  98. ?. '搞定';
  99. 尝试
  100. ..? '尝试..'; # 中
  101. 出错
  102. ..? '出错..';
  103. 收尾
  104. ..? '收尾..'; # 中
  105. 结束 尝试;
  106. ?. '搞定';
  107. 尝试
  108. ..? '尝试..'; # 中
  109. ..? 1 / 0;
  110. ..? '1 / 0';
  111. 出错
  112. ..? '出错..'; # 中
  113. ..? @ & '..'; # 中
  114. 收尾
  115. ..? '收尾..'; # 中
  116. 结束 尝试;
  117. ?. '搞定';
  118. 尝试
  119. ..? '尝试..'; # 中
  120. ..抛出 "停止!";
  121. ..? '停止!';
  122. 出错
  123. ..? '出错..'; # 中
  124. ..? @ & '..'; # 中
  125. 收尾
  126. ..? '收尾..'; # 中
  127. 结束 尝试;
  128. ?. '搞定';
True True 1 你好, 世界! 1 123456789..搞定 8642..搞定 123456789..搞定 987654321..搞定 123456789..搞定 987654321..搞定 12345..搞定 54321..搞定 尝试..搞定 尝试..收尾..搞定 尝试..收尾..搞定 尝试..出错..Floating point division by zero..收尾..搞定 尝试..出错..停止!..收尾..搞定
下载该演示
  1. =and
  2. =as
  3. =while
  4. =bit
  5. =false
  6. 再如=elsif
  7. 出错=except
  8. 函数=fun
  9. =then
  10. =to
  11. 单线=atom
  12. 取余=mod
  13. 变量=var
  14. 否则=else
  15. 如果=if
  16. 尝试=try
  17. 属于=in
  18. 异或=xor
  19. 引用=use
  20. =case
  21. 循环=loop
  22. =or
  23. 执行=do
  24. 抛出=raise
  25. 收尾=finally
  26. 整除=div
  27. =new
  28. =is
  29. =when
  30. =true
  31. =null
  32. =class
  33. 结束=end
  34. =for
  35. 跳出=exit
  36. 跳过=next
  37. 返回=return
  38. 递增=step
  39. =not
下载该库

-- [全文完] - Funlang.org