筆者の動作環境は,Nemerle入門の目次をご覧ください.
ダウンロードとインストール
このページからダウンロードできます.
残念ながら,最近のVisual Studioには拡張機能が対応していません.
Nemerleとは
C#,Lisp,Ruby,Python等,沢山の言語機能を詰め合わせた.NET Frameworkで動く言語です.
Macro(メタプログラミング)
Nemerleの注目機能の一つ,Macroによって,柔軟なメタプログラミングができます.
今後紹介する,if文,foreach文などの文はほとんどMacroによって実装されています.色々工夫すれば,Nemerleを様々な言語の書き方で書けるようになります.この機能によって,アスペクト指向プログラミング,部分評価,ドメイン固有言語の組み込みとかできるらしいです.(Wikipediaより)
関数型プログラミングがC#よりもやりやすく,F#よりC#風に書ける
Nemerleはそれぞれの言語の良さを取り入れている(主観)ので,イケてます.
イケてる型推論
def li = List(); //コンストラクタで初期化
//liはジェネリック型List[T]と宣言される
def n = 1;
//int型のnを宣言,1を代入
li.Add(n);
//liはList[int]と型推論される.
li.Add("Nemerle");
//デキナイヨ
もちろん,C#はできません.
var li = new List<>(); //Compile Error!
//デキナイヨ
var n = 1;
//int型のnを宣言,1を代入
li.Add(n);
//だからliってナンゾヤ
li.Add("Nemerle");
//だから,デキナイヨ
プロジェクトの作成,どこにコード書く?
Visual Studioから新しいNemerleのConosleProjectを作ってください.
こんな感じのソースコードが出てくるはずです.
using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;
using System;
using System.Collections.Generic;
using System.Console;
using System.Linq;
module Program
{
Main() : void
{
WriteLine("Hi!");
_ = ReadLine();
}
}
実行してみて,"Hi!"が表示されて,なんか入力して,Enter押すと黒画面が閉じるはずです.
これから,"WriteLine("Hi!")"の部分を書き換えていきます.
変数・定数,初期化,代入(束縛)
宣言
mutable name : type = value
def name : type = value
または
mutable name = value
def name = value
nameには変数名,typeには型名,valueは値を入れます.
変数はmutable,定数はdefを用います.
上は,型を指定して宣言,下は,型推論をしています.型推論の場合,宣言時に型がわかるような代入・初期化をしなくても結構です.
mutable x = null; //xってどうなるの?
x = Console.ReadLine(); //ReadLineの戻り値はstring.すなわち,xはstring型なのか!!
初期化(コンストラクタの呼び出し)
intなど,プリミティブ型などは,def hoge = 1
で結構ですが,その他は,コンストラクタを呼ぶ必要があります.ここでは,一般的な型のコンストラクタの呼び出しを説明します.
def name = type_name(arguments) //非ジェネリック型
//例
def string_builder = StringBuilder();
def name = type_name.[T](arguments) //ジェネリック型
//例
def lazy_object = Lazy.[string]();
クラス変数を指定しながら初期化
文法がC#と少し違います.
class some {
public n : int;
public m : int;
public this() {
WriteLine("Constractor is called.");
}
}
def s : some = some() <- {
n = 0;
m = 0;
}
代入(束縛)
C#などと同じ "=" イコールで代入します.
プリミティブ型
条件分岐
条件分岐に関す売る演算子(比較演算子,条件演算子)
条件がTrueの場合,Falseの場合で分岐させる(if文)
if(condition) {
A
} else {
B
}
両方共,conditionがTrueの時は,Aのコードを,Falseの時は,Bのコードを実行します.
C#のようにカッコを省略することができます.しかし,elseは省略できません.
条件がTrueの場合のみ実行する(when文)
when(condition) {
Code
}
conditionがTrueの時,Codeが実行されます.
条件がFalseの場合のみ実行する(unless文)
unless(condition) {
Code
}
conditionがFalseの時,Codeが実行されます.
(when文で,論理否定演算子使って済ませることが自分は多いので,影が薄い文です.)
コメント
C#,C++と同じです.
//一行コメント
/*
複数行コメント
*/
スプリクト言語風書き方
プロジェクト作成時のMain.nは,(usingの部分は省いてます.)
module Program {
Main() : void {
WriteLine("Hi!");
_ = ReadLine();
}
}
こうなっていたと思います.これらをコメントアウトしてください.(Ctrl + K,C)
そして以下のソースコードをコピペして,実行してみてください.
WriteLine("Hi!");
_ = ReadLine();
実行できましたね?このように,スクリプト言語のように書くこともできます.
(C# 10にも同様の機能が実装されました.)
アクセス修飾子
publicやprivate等,C#と同じです.
現在,
static,volatile,partial
これらもC#と同じです.
メソッド
Method_Name(Parm1 : type, Param2 : type...) : Return_Type {
Code
}
書式はこんな感じ.F#っぽいかな?これだけ見てもわからないので,具体例を示しましょう.
void HogeHogeMethod(int start, int count) {
//DoSomething
} //C#
let hogeHogeMethod (start : int, count : int) =
//DoSomething
()
HogeHogeMethod(start : int, count : int) : void {
//DoSomething
} //Nemerle
上の3つはほぼ同じです.
書き方はC#をF#みたく書いた感じでしょうか.
属性の付け方はC#と同じです.
関数
C#ならば,
int Add(int x, int y) {
return x + y;
}
ですが,Nemerleでは,returnは要りません.最後の式の戻り値が返されます.
Add(x : int, y : int) : int {
x + y;
}
namespace
C#/VB.netのnamespaceと同じです.
namespace hoge {
class hoge {
...
}
module hogeUtil {
...
}
}
class
C#/Vb.netのclassと同じです.
クラスを定義することができます.
クラスの定義の仕方は後で詳しく説明します.
class hoge {
mutable a : int;
}
Main() : void {
def h = hoge();
h.a = 0;
WriteLine(h.a); // 0
}
module
VisualBasic .Netのmoduleと同じです.C#で言う,static classのようなものです.
moduleの中に書いた物は自動的にStaticになります.
インスタンス化はできないので,通常のクラスのコンストラクタなどは作れません.
module Num {
Add(x : int, y : int) : void {
x + y
}
}
Main() : void {
Console.WriteLine(Num.Add(3, 5)); // 8
def n : Num = Num(); // Error!!
}
クラスの定義
Nemerleでも,もちろん.Netのクラスを定義することができます.他の言語と同じで,プロパティなども定義することができます.そこまで,C#/VB .netと差異は無いので軽く流します.
class IntPair {
mutable a : int; //メンバ変数(アクセス修飾子がないので,自動的にprivateになる)
public mutable b : int; //アクセス修飾子がつけられる
private c : int; //局所定数(変更はできない)
static class_name : string = "IntPair";
//staticをつければ静的に,”=”で代入もできる
public A : int { //プロパティ,C#と同じなので,そこまで気にしなくていい
get{
WriteLine("A is called!");
a;
} set{
a = value;
}
}
public D : int { get; } //getオンリーなプロパティもこの一行でおk
public this() { //コンストラクタ
a = 0;
b = 0:
c = 0;
}
public static this() { //静的なコンストラクタ
WriteLine("IntPair!");
}
}
残念ながら,C# 9のinit
には対応していません.
構造体: struct
class
ではなく,struct
にすることで構造体を生成できます.
struct StructBox {
public mutable x : double = 0;
public mutable y : double = 0;
}
レコード: Record
class
もしくはstruct
に[Record]
マクロをつけると,C# 10のレコードのようになります.
[Record]
class Point {
public mutable x : double = 0;
public mutable y : double = 0;
}
キャスト
Nemerleにキャストは2種類あります.
厳密な型変換(:)
コンパイル時にチェックされ,型変換できるかわからない時は,コンパイルエラーを吐きます.
def s : short = 72;
WriteLine(200000000 / (s : long)); // short → longは元がどんな状態でも変換できるので,おk
def obj : object = 18;
WriteLine(200000000 / (obj : long)); // Compile Error!
普通の型変換(:>)
実行時にチェックされ,失敗した場合,InvalidCastException
を投げます.
def a : object = "abc";
WriteLine(20000000 / (a :> long)); // コンパイルエラーはないけど,例外投げる