Quick summary of differences between Nemerle and C#

1. Introduction

This document lists basic differences between Nemerle and C# in a terse form. If you know Java or C++ you also should be able to use it.

2. Changes in expressions

C#NemerleRemarks
int x = 3;
string y = "foo";
FooBarQux fbq = make_fbq ();
def x = 3;
def y = "foo";
def fbq = make_fbq ();
The values of x, y and fbq cannot be changed. More info.
int x = 3;
string y = "foo";
FooBarQux fbq = make_fbq();
mutable x = 3;
mutable y = "foo";
mutable fbq = make_fbq();
The values of x, y and fbq can be changed. More info.
expr_1 = expr_2 = expr_3; def tmp = expr_3;
expr_1 = tmp;
expr_2 = tmp;
The type of assignment operator is void.
new Class (parms) Class (parms) The new keyword for creating an object is dropped.
new Class [size] array (size) If the type can be inferred (most of the time).
new Class [size] (array (size) : array <Class>) If the type cannot be inferred.
new Type[] { expr_1, expr_1, ..., expr_n } array [expr_1, expr_1, ..., expr_n] The array constructor.
if (cond) return foo;
do_something ();
return bar;
if (cond) foo
else {
do_something ();
bar
}
There is no return statement that cuts control flow in Nemerle.
if (cond) answer = 42;
...
when (cond) answer = 42;
...
The if without else is called when.
if (!cond) answer = 42;
...
unless (cond) answer = 42;
// or: when (!cond) answer = 42;
...
The if without "then" is called unless. However nobody is forced to use it.
try ...
catch (FooException e) { ... }
catch (BarException e) { ... }
try ...
catch {
| e : FooException => ...
| e : BarException => ...
}
Somewhat different syntax, consistent with match though.
((type) expr) (expr :> type) Runtime type cast, allows for downcasts and upcasts.
((type) expr) (expr : type) Static cast, allow only upcast.
using System;
using SWF = System.Windows.Forms;
using System.Xml;
...
Console.WriteLine ("foo");
SWF.Form x = new SWF.Form ();
XmlDocument doc = new XmlDocument ();
using System;
using System.Console;
using SWF = System.Windows.Forms;
...
WriteLine ("foo");
def x = SWF.Form ();
def doc = Xml.XmlDocument ();
In Nemerle you can also apply using directive to classes. Opened namespaces allow to cut prefix of other namespaces like System in System.Xml. More info.
System.Windows.Forms.Button button = control as System.Windows.Forms.Button;
if (button != null) ...
else ...
match (control) {
| button : System.Windows.Forms.Button => ...
| listv : System.Windows.Forms.ListView => ...
| _ => ...
}
Expression returning null value if variable is of given type must be simulated with a little bit longer construct, but pattern matching is more general and powerful feature for most of the tasks where as would be used.
x++; ++x; The ++ (and -- for that matter) is only available in the prefix form right now.

3. Changes in type definitions

C#NemerleRemarks
static int foo (int x, string y) { ... } static foo (x : int, y : string) : int { ... } Types are written after variables.
class Foo {
public Foo (int x) { ... }
}
class Foo {
public this (x : int) { ... }
}
Constructor name is always this.
class Foo : Bar {
public Foo (int x) : base (x) { ... }
}
class Foo : Bar {
public this (x : int) { base (x); ... }
}
Base constructor is called in function body.
class Foo {
int x;
}
class Foo {
mutable x : int;
}
Fields to be changed outside the constructor need to be marked mutable.
class Foo {
readonly int x;
}
class Foo {
x : int;
}
readonly is the default.
class C : I1, I2 {
void I1.m () { ... }
void I2.m () { ... }
}
class C : I1, I2 {
meth1 () : void implements I1.m { ... }
meth2 () : void implements I2.m { ... }
}
When two interfaces have the method with the same name.

4. As in Generic C#...

Syntax and semantics of parametric polymorphism in Nemerle is the same as what is called generics in C# 2.0. There is, however, a naming convention of type variables with identifiers like 'a. You do not need obey it though.

C#NemerleRemarks
class A <T> { readonly T x; } class A <'t> { x : 't; }
class A <T> where T : IComparable <T> { ... } class A <'t> where 't : IComparable <'t> { ... } Type parameters are written in parens <>.
class A <T> where T : IFoo, IBar { ... } class A <'t> where 't : IFoo, IBar { ... }
class A <X,Y> where X : IFoo, IBar where Y : IBaz { ... } class A <'x,Y> where 'x : IFoo, IBar where Y : IBaz { ... } Multiple type variables. ' is optional, but it is a common naming convention in functional programming.
int meth<A> (A x) { ... } meth<'a> (x : 'a) : int { ... } Polymorphic method.
int meth<A> (A x)
where A : IFoo { ... }
meth<'a> (x : 'a) : int
where 'a : IFoo { ... }
Polymorphic method with constraints.

5. New stuff

This section talks about the stuff more or less absent in C#.

C#NemerleRemarks
void m(int _unused1, string _unused2) { ... } m (_ : int, _ : string) : void { ... } Upon each use the _ keyword generates a new name.
class Foo { static readonly int x; static int m () { ... } } module Foo { x : int; m () : int { ... } } module is a class, that have all members static.

There are other things, that don't fit here very well (this document should be a short list of differences), so we just give some links.

6. The same

This section lists things that are written (mostly) the same way as they are in C#. It only includes cases when it could be doubtful.

C#NemerleRemarks
// A comment.
/* A possibly multiline
comment. */
// A comment.
/* A possibly multiline
comment. */
throw new System.ArgumentException ("foo"); throw System.ArgumentException ("foo") throw is the same (but new is dropped).
@"foo\bar" @"foo\bar" Quoted string literals.
using Foo; using Foo; In Nemerle one can be using classes in addition to namespaces.
try { foo (); bar (); }
catch (Exception e) { baz (); }
finally { qux (); }
try { foo (); bar () }
catch { e : Exception => baz () }
finally { qux () }