Nemerle

型推論

def x = 1;           // intdef myList = List(); // ジェネリック型 List[T] として宣言され、その後の使われ方から推論されるmyList.Add(x);       // コンパイラにより myList は List[int] と推論される

全ては式である

def x =
  { // x = 3 と等しい
    def y = 1;
    def z = 2;
    y + z   // 最後に評価された値が返される
  };def x =
  if (DateTime.Now.DayOfWeek == DayOfWeek.Monday)  // if、using、try なども全て式である
    "Monday"
  else
    "other day";def x = try int.Parse(someString)
        catch { | FormatException() => 0 };def x = returnBlock : 
  {
    foreach (i in [1, 2, 3])
      when (i > 2)
        returnBlock(true); // ブロックを抜ける ( x = true となる )

    false // x = false
  };

タプル

def k = (1, "one"); // k : (int * string)def (a, b) = k; // a = 1, b = "one"

パターンマッチ

def result = match (number){
  | 0            => "zero"
  | 1            => "one"
  | x when x < 0 => "negative"
  | _            => "more than one"}

関数型とローカル関数

using System.Console; // クラスとモジュール(静的クラス)を名前空間として使用できるdef next(x) { x + 1 }; // 引数 x の型は使われ方から推論されるdef mult(x, y) { x * y };def fibonacci(i){
  | 0     => 0
  | 1     => 1
  | other => fibonacci(i - 1) + fibonacci(i - 2)};WriteLine(next(9));        // 10  "Console.WriteLine(next(9));" と等しい WriteLine(mult(2, 2));     // 4WriteLine(fibonacci(10)); // 55

バリアント

バリアント (代数的データ型とも) は複数の種類の値を表現できる:
 variant RgbColor{
   | Red
   | Yellow
   | Green
   | Different {
       red : float;
       green : float;
       blue : float;
     }
 }

メタプログラミング

Nemerle のマクロ機能は、コンパイル中にプログラム中のコードの生成・解析・編集を可能にする。マクロは通常のメソッド呼び出しとして使えるほか、構文を定義して用いることもできる。Nemerleの多くの構文(if、for、foreach、while、usingなど)はマクロによって定義されている。
"if" マクロの例:
macro @if (cond, e1, e2)syntax ("if", "(", cond, ")", e1, Optional (";"), "else", e2){
  /*    <[ ]> はコードクォートであり、Nemerleコンパイラは中身を構文木に変換して提供する。    C# における式木に似ているところがある。  */
  <[    match ($cond : bool)
    {
      | true => $e1
      | _ => $e2
    }
  ]>}// コード中でマクロを使う:def max = if (a > b) a else b;// コンパイル中に上のコードは下のように展開される:def max = match (a > b){
  | true => a
  | _    => b}

統合開発環境

NemerleはVisual Studio 2008に統合することができる。Visual Studio 2008 Shellをベースとした無料のIDEも存在する。
また、SharpDevelop用のプラグインも用意されている(プラグインのページ)。
アドインによりVisual Studio 2010にも統合が可能で、Visual Studio 2013版も存在している。

Hello, World!

伝統的なHello worldは、次のようにC#ライクなスタイルで書くことができる。
 class Hello {
   static Main () : void {
     System.Console.WriteLine ("Hello, world!");
   }
 }
あるいは、よりシンプルに
 System.Console.WriteLine("Hello, world!");
とも書ける。

文字列フォーマット

$ 記号により文字列中に値を展開することができる:
def s = $"The number is $i"; // $i を変数 i の値で置き換える def s = $"$x + $y = $(x+y)"; // $(...) を使うことで複雑な式も展開できる

コード生成

StructuralEquality、Memoize、json、withなどはコンパイル時にコードを生成するマクロである。
いくつかのマクロ(StructuralEquality, Memoize)はC#における属性のように見えるが、コンパイル時に適切なコードへの変換を行う。
[StructuralEquality] // IEquatable[Sample] インターフェースを自動で実装するマクロclass Sample{   [Memoize]  // 最初の計算結果を保持する
   public static SomeLongEvaluations() : int  
   {
       MathLib.CalculateNthPrime(10000000)
   }   [DependencyProperty] // WPF 依存関係プロパティ
   public DependencyPropertySample { get; set; }
   
   public static Main() : void
   {/* 構文マクロ "json" は次のようなコードを生成する:JObject.Object([("a", JValue.Number(SomeLongEvaluations())), ("b", JValue.Number(SomeLongEvaluations() + 1))])*/
       def jObject = json { a: SomeLongEvaluations(); b: (SomeLongEvaluations() + 1)} 
// オブジェクト初期化マクロ "<-" はC#のオブジェクト初期化子と同じ機能を提供する
       def k = Diagnostics.Process() <- 
       {
          StartInfo <- // コンストラクタ呼び出しなしに内部のプロパティの初期化を行える
          {
              FileName = "calc.exe";
              UseShellExecute = true;
          }   
          Exited += () => WriteLine("Calc done"); // イベントとデリゲート
       }

       ReadLine();
   }}

データベースへのアクセス

例えば、Nemerleのマクロを用いてSQL文を発行するコードは以下のように書くことができる。
 ExecuteReaderLoop ("SELECT firstname, lastname FROM employee WHERE firstname = $myparm", dbcon,
 {
   System.Console.WriteLine ("Name: {0} {1}", firstname, lastname) 
 });
これは、次の文の代わりに用いられる。
 string sql = "SELECT firstname, lastname FROM employee WHERE firstname = :a";
 NpgsqlCommand dbcmd = new NpgsqlCommand (sql, dbcon, dbtran);
 dbcmd.Parameters.Add("a", myparm);
 
 NpgsqlReader reader = dbcmd.ExecuteReader();
 
 while(reader.Read()) {
   string firstname = reader.GetString (0);
   string lastname = reader.GetString (1);
   System.Console.WriteLine ("Name: {0} {1}", firstname, lastname) 
 }
 reader.Close();
 dbcmd.Dispose();
これは、ライブラリ中の幾つかの動作を隠すだけでなく、クエリ文字列や変数、データベースから返されたコラムがコンパイラによって理解され実行されるということを表している。ExecuteReaderLoopマクロは、プログラマが記述しなければならないコードと同等のコードを生成させることができる。またSQL文が正しいかどうかをコンパイル時に検査することも可能である。

新しい言語の実装

Nemerleのマクロを用いると、言語に新しい構文を導入することも可能である。
 macro ReverseFor (i, begin, body) 
 syntax ("ford", "(", i, ";", begin, ")", body)
 {
   <[ for ($i = $begin; $i >= 0; $i--) $body ]>
 }
この例ではford ( EXPR ; EXPR ) EXPR構文を定義していて、この構文は次のように用いることができる。
 ford (i ; n) print (i);

NemerleとASP.NET

NemerleはASP.NET上に直接組み込むことが可能である。
<%@ Page Language="Nemerle" %>
 <script runat="server">
 
     Page_Load(_ : object, _ : EventArgs) : void {
         Message.Text = $"You last accessed this page at: $(DateTime.Now)";
     }
 
     EnterBtn_Click(_ : object, _ : EventArgs) : void {
         Message.Text = $"Hi $(Name.Text), welcome to ASP.NET!";
     }
 
 </script>
 
 <html>
     <body>
         <form runat="server">
             Please enter your name: <asp:TextBox ID="Name" runat="server" />
             <asp:Button OnClick="EnterBtn_Click" Text="Enter" runat="server" />
 
             <p><asp:Label ID="Message" runat="server" /></p>
         </form>
     </body>
 </html>
また、別ファイルにコードを記載し、それを呼び出すことも可能である。
<%@ Page Language="Nemerle" Src="test.n" Inherits="Test" %>

P/Invoke

Nemerleはネイティブのプラットフォームライブラリを呼び出すことができる。その構文はC#やその他の.NET言語に非常に似ている。
 using System;
 using System.Runtime.InteropServices;
 
 class PlatformInvokeTest
 {     [DllImport("msvcrt.dll")]
     public extern static puts(c : string) : int;       [DllImport("msvcrt.dll")]
     internal extern static _flushall() : int;
     
     public static Main() : void
     {
         _ = puts("Test");
         _ = _flushall();
     }
 }