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.
C# | Nemerle | Remarks |
---|
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.
|
C# | Nemerle | Remarks |
---|
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.
|
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# | Nemerle | Remarks |
---|
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.
|
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.
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.