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_1 <- expr_2; The assignment operator. 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 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.
{ 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;
...
Console.WriteLine ("foo");
using System.Console;
...
WriteLine ("foo");
In Nemerle you can also apply using directive to classes. More info.
while (x < 7) {
y += x;
x++;
}
System.Console.WriteLine (y);
while (x < 7) {
y <- y + x;
x <- x + 1;
};
System.Console.WriteLine (y);
Note semicolon after while {...}. [[FIXME: shouldn't we have ++ += etc?]]
for (int x = 0; x < 7; x++) {
y += x;
}
System.Console.WriteLine (y);
for (mutable x <- 0; x < 7; y <- y + x) {
x <- x + 1;
};
System.Console.WriteLine (y);
Note semicolon after for {...}.

3. Changes in type definitions

C#NemerleRemarks
static int foo (int x, string y) { ... } static foo (x : int, y : string) : int { ... } Type 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 conversion to name type variables with identifiers like 'a. You do not need obey it though.

C#NemerleRemarks
class A <T> { readonly T x; } class A <'t> { 't x; }
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.
int meth<A> (A x) { ... } meth<'a> ('a x) : int { ... } Polymorphic method.
int meth<A> (A x)
where A : IFoo { ... }
meth<'a> ('a x) : 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 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.
using System;
Messaging.Message msg1 = Messaging.Message ();
Windows.Forms.Message msg2 = Windows.Forms.Message.Create (null, 0, null, null);
namespace Msg = System.Messaging;
namespace SWF = System.Windows.Forms;
...
def msg1 = Msg.Message ();
def msg2 = SWF.Message.Create (null, 0, null, null);
More info.

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 () } finally { baz () } try { foo (); bar () } finally { baz () }