测试Open Live Writer

 

近10年D语言在社区驱动下得到巨大发展,语言核心去芜存菁,广泛吸收;标准库不断扩充;语法越来越“对人类友好”;betterC和importC使得D语言与C语言越来越成为一家人,为底层开发在做坚实的奠基;以vibe-d和hunt frame work为首的众多跨平台网络库,使得开发web框架和应用几乎与控制台和桌面程序一样的容易、简

UFCS,Uniform Function Call Syntax.统一函数调用语法,或者,我按自己的理解,称为函数一致性调用语法,使得语言更贴近人类表达习惯,同时使得函数链调用变得非常可行,并且简单、简便。

 

对于一个模块级(module)自由函数,如果满足以下两个条件,即可像一个对象的成员方法一样去调用:

  • 这个对象没有(或不能有)一个这样的成员方法;
  • 这个自由函数的第一个参数与该类型匹配(该类,super类,可安全地类型转换成为该类型等)

到此,这个对象可以是任何类型,都可有如调用自己的成员方法一样去调用这个自由成员。

听起来还是有些别扭,看示例会更容易明白究竟是怎么一回事:

  1 /+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2 这个小程序演示D语言UFCS,函数一致性调用语法。
  3 一般地,如果有一个模块级自由函数void print(string msg),
  4 我们理所当然地这样去调用:
  5 print("早上好!");
  6 
  7 当以下两件条件满足时:
  8 1.string类型没有print()这样一个方法;
  9 2.自由函数的参数类型为string,正好是string类型
 10 
 11 string.print() 即可通过编译器允许,即与
 12 print("早上好”);
 13 一样。
 14 事实上由于UFCS这个特性,编译器首先查看string类型有没有
 15 print()这个方法,如果有,就调用;如果没有,则在模块级
 16 查看有没有print(stirng)这样一个自由函数,如果有,就调
 17 用它。
 18 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/
 19 
 20 module ufcstest;
 21 import std.stdio;
 22 
 23 void print(string msg)
 24 {
 25 	writeln(msg);
 26 }
 27 
 28 void main()
 29 {
 30 	"Hello UFCS".print();
 31 	"早上好".print;
 32 
 33 	readln;
 34 }

ufcstest

 

既然UFCS可以这样玩,那试试语言标准库标准输出函数writeln:

  1 module ufcstest;
  2 import std.stdio;
  3 
  4 /*
  5 void print(string msg)
  6 {
  7 	writeln(msg);
  8 }
  9 */
 10 void main()
 11 {
 12 	writeln("标准库writeln标准调用方法:");
 13 	writeln("晚上好");
 14 	writeln("我爱世界杯");
 15 
 16 	writeln("==============================");
 17 	writeln("UFCS调用:");
 18 
 19 	"晚上好".writeln();
 20 	"我爱世界杯".writeln;
 21 
 22 	readln;
 23 }

ufcstest1

下面示例一个非常简单的函数链调用:

  1 module ufcstest;
  2 import std.stdio;
  3 
  4 /*
  5 void print(string msg)
  6 {
  7 	writeln("标准库writeln标准调用方法:");
  8 	writeln("晚上好");
  9 	writeln("我爱世界杯");
 10 
 11 	writeln("==============================");
 12 	writeln("UFCS调用:");
 13 
 14 	"晚上好".writeln();
 15 	"我爱世界杯".writeln;
 16 }
 17 */
 18 
 19 double add(double a,double b)
 20 {
 21 	return a+b ;
 22 }
 23 
 24 void main()
 25 {
 26 	writeln("比起嵌套调用:writeln(add(10,20));");
 27 	writeln("add(10,20).writeln更符合连贯性思维。");
 28 	add(10,20).writeln;
 29 
 30 	readln;
 31 }

ufcstest2

可以初步稍稍想象一下,类成员函数有一些是返回类对象本身,再结合自由函数的UFCS,加之标准库,泛型,mixin等语言核心特性在一起,这个组合将是非常强大的。

最后我们借用网上的一段代码来结束这趟Open Live Writer之旅。对一个数组内元素进行加减乘除的操作然后打印到控制台,还是借用标准输出泛型自由函数writeln(T...)(T args)第一个参数可以是任何类型的这个特性,对数组操作进行链式函数调用。

  1 module chaincall;
  2 
  3 import std.stdio;
  4 
  5 //数组slice每个元素被除以divisor后,返回整个数组
  6 int[] divide(int[] slice,int divisor)
  7 {
  8 	int[] result;
  9 	result.reserve(slice.length);
 10 
 11 	foreach(value;slice)
 12 	{
 13 		result~=value/divisor;
 14 	}
 15 	return result;
 16 
 17 }
 18 
 19 //数组slice每个元素被乘以multiplier后,返回整个数组
 20 int[] multiple(int[] slice,int multiplier)
 21 {
 22 	int[] result;
 23 	result.reserve(slice.length);
 24 
 25 	foreach(value;slice)
 26 	{
 27 		result~=value*multiplier;
 28 	}
 29 	return result;
 30 }
 31 
 32 //去除掉数组里的偶数元素,返回结果数组
 33 int[] evens(int[] slice)
 34 {
 35 	int[] result;
 36 	result.reserve(slice.length);
 37 
 38 	foreach(value;slice)
 39 	{
 40 		if(value%2)
 41 		{
 42 			result~=value;
 43 		}
 44 	}
 45 	return result;
 46 }
 47 
 48 void main()
 49 {
 50 	int[] values=[1,2,3,4,5];
 51 	//WYSIWYG所见即所得字符串表达方式:
 52 	string prompt="
 53 	对数组values进行以下操作:
 54 	第一步:对各个元素乘以10;
 55 	第二步:对各个元素除以3;
 56 	第三步:返回只有奇数值的数组;
 57 	第四步:打印结果数组(只有奇数值)
 58 
 59 	一般强类型编译型语言基本都是这样调用的:
 60 
 61 	";
 62 	prompt.writeln;
 63 	writeln("writeln(evens(divide(multiple(10),3)));\n结果是:");
 64 	writeln(evens(divide(multiple(values,10),3)));
 65 	writeln("这个调用顺序显然不符合上面所列,即非原本所思");
 66 
 67 	writeln("且看D语言UFCS调用语法,其顺序和人想的一样:");
 68 	writeln("writeln(values.multiple(10).divide(3).evens());\n");
 69 
 70 	writeln("或者干脆:\nvalues.multiple(10).divide(3).evens.writeln;\n结果是:\n");
 71 	values.multiple(10).divide(3).evens.writeln;
 72 
 73 	writeln("Done.");
 74 	readln;
 75 }

ufcstest3

posted @ 2023-04-18 20:12  高斯山  阅读(15)  评论(0编辑  收藏  举报