3月31日,Nemerle发布了它的0.2.10版本。在这篇文章中,我们通过Nemerle的Tutorial来看看这种.net上的新语言。
Nemerle is a new functional language designed from the ground up for the .NET. In this paper we have focused on features absent in traditional ML-like and object-oriented languages: variant inheritance, assertions and powerful code-generating macros. We also gave concern for the syntax and the “spirit” of Nemerle that makes it a good transition language for programmers with C# background.
这是Nemerle的intro里对它的介绍,为了保证准确性,我们引用了全文。而它的一些特性我们通过下面的几个例子来概览Nemerle.












这个程序实现了输入两个数并输出他们的和。从这段代码里,我们可以清晰的看到void等返回类型都写到了右边的冒号后面,而且在使用using的时候,引用的不单单是命名空间(namespace),还可以引用类的成员了,这样使得我们的WriteLine()和ReadLine()函数都可以直接的使用。
我们换一种方式来实现


















事实上我们更希望使用这种方法来实现我们的目的。在Main()函数里我们
定义了两个值x和y,是通过def关键字实现的,您也看到了我们并没有写出
变量究竟是什么类型的,编译器看到ReadInteger返回int型后就把x定义
为int型变量了。我们称之为类型推断(Type Inference)
所以,我们可以这样用,new关键字也不需要了。
下面的这个程序是读出一个文本文件有多少行:class LineCounter
{
public static Main () : void
{
// Open a file.
def sr = System.IO.StreamReader ("SomeFile.txt"); // (1)
mutable line_no = 0; // (2)
mutable line = sr.ReadLine ();
while (line != null) { // (3)
System.Console.WriteLine (line);
line_no = line_no + 1; // (4)
line = sr.ReadLine ();
}; // (5)
System.Console.WriteLine ("Line count: {0}", line_no);
}
}
这里体现了很多值得我们注意的地方。首先,(1)和(2)两个地方就非常不一样,(1)中
我们定义了一个不可变的值(immutable value),他们都是一旦建立就永远不会改变的。
(2)中我们定义了一个可变的值(mutable value),它很像C#里的变量,必须初始化才
能使用,并且还可以改变它的值。在(3)中我们使用的很像C#中的while语句,同样,
你也可以使用do…while的。Functional programming (FP) is style in which you do not modify
state of the machine with instructions, but rather evaluate functions
yielding new and new values. That is entire program is just one big
expression. In purely functional language (Haskell being main example)
you cannot modify any objects once they are created (there is no
assignment operator, like = in Nemerle). There are no loops,
just recursive functions.在Nemerle里我们不一定非要使用FP编程方式,但是当你想用的时候可以随心所欲。修改
一下上面的代码:class LineCounterWithoutLoop
{
public static Main () : void
{
def sr = System.IO.StreamReader ("SomeFile.txt");
mutable line_no = 0;
![]()
def read_lines () : void { // (1)
def line = sr.ReadLine ();
when (line != null) { // (2)
System.Console.WriteLine (line); // (3)
line_no = line_no + 1; // (4)
read_lines () // (5)
}
};
![]()
read_lines (); // (6)
![]()
System.Console.WriteLine ("Line count: {0}", line_no); // (7)
}
}
这段代码的思路还是比较好理解的,就是一段递归程序。文本文件有多少
行,read_lines()函数就要执行几次,像使用while循环一样,只不过稍
微换了一种思路。这时候可能您会考虑到使用递归而影响效率的问题,事实是
当一个函数主体在调用另一个函数后执行完毕,没有创建任何新的堆栈,这
被称作尾端调用(Tail Call),所以这段代码和while循环在效率上一样的。
Nemerle尤其注重将循环写成递归的深入的理解,文中用Grok来形容这种理
解的程度,可见其重要性。需要提到的一点是,使用if的时候必须使用else语句。上面的这段程序还不是完全符合FP要求的,改写一下:class FunctionalLineCounter
{
public static Main () : void
{
def sr = System.IO.StreamReader ("SomeFile.txt");
def read_lines (line_no : int) : int { // (1)
def line = sr.ReadLine ();
if (line == null) // (2)
line_no // (3)
else {
System.Console.WriteLine (line); // (4)
read_lines (line_no + 1) // (5)
}
};
![]()
System.Console.WriteLine ("Line count: {0}", read_lines (0)); // (6)
}
}
这段程序从(3)处结束并返回结果,而参数的累加结果正是最后输出的line_no的值.最后需要提到的是类型推断还可以用在函数的参数和返回类型上,当然是有一定说法
的,更详细的内容从其官方网站上可以看到