|
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. |
= ; | <- ; | The assignment operator. More info. |
= = ; |
def tmp = <- tmp; <- tmp; | ;The type of assignment operator is void. |
new | ( )( ) | The new keyword is dropped. |
new | [ ]array ( | )If the type can be inferred (most of the time). |
new | [ ](array ( | ) : array ( ))If the type cannot be inferred. |
{ | , , ..., }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; ... 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 {...}. |
C# | Nemerle | Remarks |
---|---|---|
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. |
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# | Nemerle | Remarks |
---|---|---|
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. |
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 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.
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 () } finally { baz () } | try { foo (); bar () } finally { baz () } |