Quick summary of differences between Nemerle and C#

Google search:

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 is FooException => ...
  | e is 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.
using System.Windows.Forms;

Button button = control as Button;

if (button != null) 
  ...
else 
  ...
match (control) {
  | button is Button => ...
  | listv is 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.
int y = x++;
++x;
def y = x;
x++;
++x;
The ++ (and -- for that matter) return void just like assignment. So both prefix and postfix versions are equivalent.

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.
using System.Runtime.CompilerServices.CSharp;

class C {
  public object this [int i] 
  { ... }

  [IndexerName("MyItem")]
  public int this [string name] 
  { ... }
}
class C {
  public Item [i : int] : object 
  { ... }

  public MyItem [name : string] : int 
  { ... }
}
Nemerle allows defining named indexers in an easier way, just like in VB.NET.

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; }
Type parameters are written in parens [...].
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 () 
}