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;
expr_1 <- expr_2; // obsolete
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.
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;
...
Console.WriteLine ("foo");
using System.Console;
...
WriteLine ("foo");
In Nemerle you can also apply using directive to classes. More info.
x++; ++x; The ++ (and -- for that matter) is only prefix 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 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 (); }
catch (Exception e) { baz (); }
finally { qux (); }
try { foo (); bar () }
catch { e : Exception => baz () }
finally { qux () }