|
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. |
= = ; |
def tmp = = tmp; = tmp; | ;The type of assignment operator is void. |
new | ( )( ) | The new keyword for creating an object is dropped. |
new | [ ]array ( | )If the type can be inferred (most of the time). |
new | [ ](array ( | ) : array < >)If the type cannot be inferred. |
new | [] { , , ..., }array [ | , , ..., ]The array constructor. |
if ( ; return ; | ) return ;
if ( else { ; } | ) There is no return statement that cuts control flow in Nemerle. |
if ( ... | ) answer = 42;
when ( ... | ) answer = 42;The if without else is called when. |
if (! ... | ) answer = 42;
unless ( // or: when (! ) answer = 42; ... | ) 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. |
(( | ) )( | :> )Runtime type cast, allows for downcasts and upcasts. |
(( | ) )( | : )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. |
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. |
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; } | |
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. |
This section talks about the stuff more or less absent in C#.
C# | Nemerle | Remarks |
---|---|---|
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.
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# | Nemerle | Remarks |
---|---|---|
// 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 () } |