Nemerle是微软的研究项目之一,由 Wrocław 大学的Kamil Skalski、Michał Moskal、Prof. Leszek Pacholski、Paweł Olszt等人发明.
Nemerle是一种多范型语言(面向对象和函数式),完全支持编译器宏(后来更多的是Lisp的变种,而不是C++),以及许多其他的东西。Nemerla与VS2010里发布的F#不同,后者是纯函数式语言。
Nemerle提供了与C#近似的语法和强大的元编程系统。有关meta-program可以参考:http://en.wikipedia.org/wiki/Metaprogramming
你可以在http://nemerle.org/Main_Page下载它的***发布,在发布包中还带有与visual studio的集成的IDE,可以很方便地学习Nemerle这种多范型语言,***版本是0.9.7。
最传统的"Hello,World"
- using System.Console;
- class Hello {
- static Main () : void {
- WriteLine ("Hello, world!");
- }
- }
Nemerle语言具有与C#近似的语法,无疑这使得学习曲线大幅下降。这里有几个与C#版"Hello,World"不同的地方:
1. void等返回类型都写到了右边的冒号后面
2. 在使用using的时候,引用的不单可以是命名空间(namespace),还可以引用类的成员,这样使得我们的WriteLine()函数都可以直接的使用。
多范型语言
- using System;
- using System.Console;
- using Nemerle.Utility;
- using System.IO;
- module Program
- {
- class LineCounter
- {
- public static Main():Void
- {
- def sr=StreamReader(@"c:\test.rb"); // (1)
- mutable line_no = 0; // (2)
- mutable line = sr.ReadLine ();
- while (line != null) {
- WriteLine (line);
- line_no = line_no + 1;
- line = sr.ReadLine ();
- };
- WriteLine ("Line count: {0}", line_no);
- }
- }
- }
这里和C#不同的地方,首先我们通过关键字def定义了一个值sr,我们并没有声明它的类型,编译器会根据上下文自动赋予类型,我们称之为类型推断(Type Inference)。而且new关键字也不需要了。后面的方法与C#完全一样,不再赘述。
在(2)的地方,我们用mutable(即:可变的)声明了一个值line_no,它很像C#里的变量,必须初始化才能使用,并且还可以改变它的值。它与(1)处的"@"C:\test.rb"不同,后者是一个不可变的值。
我们前面提过Nemerle是种多范型的语言,所以我们可以在需要的地方采用函数式编程,其他地方采用面向对象编程,无疑更具备灵活性。
上面的代码可以修改成
- using System;
- using System.Console;
- using Nemerle.Utility;
- using System.IO;
- module Program
- {
- class FunctionalLineCounter
- {
- public static Main () : void
- {
- def sr = System.IO.StreamReader (@"C:\test.rb");
- def read_lines (line_no : int) : int
- {
- def line = sr.ReadLine ();
- if (line == null)
- line_no //here
- else {
- System.Console.WriteLine (line);
- read_lines (line_no + 1)
- }
- };
- System.Console.WriteLine ("Line count: {0}", read_lines (0));
- }
- }
- }
这段程序从"//here"处结束并返回结果,而参数的累加结果正是***输出的line_no的值.
文本文件有多少行,read_lines()函数就要执行几次,像使用while循环一样,只不过稍微换了一种思路。这时候可能您会考虑到使用递归而影响效率的问题,事实是当一个函数主体在调用另一个函数后执行完毕,没有创建任何新的堆栈,这被称作尾端调用(Tail Call),所以这段代码和while循环在效率上一样的。Nemerle尤其注重将循环写成递归的深入的理解.
强大的宏
使用 Nemerle 宏(macros)可以产生新的语法。在Nemerler IDE中,添加一个macro project,并在你的程序里引用这个macro project.
- using Nemerle.Compiler;
- namespace Macro
- {
- macro forp (i, n , m , body) //(1)
- syntax("forpermutation","(",i,"from", n,"to",m,")",body) //(2)
- {
- <[ for ($i = $n; $i <= $m; $i++) $body ]>
- }
- }
在(1)处,我们定义了一个宏 forp,带有四个参数,参数默认类型是Expr,即表达式。 接下来,我们通过syntax定义了调用这个宏的语法,然后在<[...]>里定义宏的内容。
这个宏可以这样被调用
- mutable i=0;
- forpermutation(i from 3 to 4) printf("%d\r\n",i);
这样我们就创造了一个新的语法。奇怪的是,我将from换成in,Nemerle则会报错,文档中并未给出原因,个人觉得应该避免用关键字来定义语法。
【编辑推荐】