Nuの基本
Nu言語は Lisp をベースとしているので、Lisp になじみのない方には不思議な印象を受けるかもしれませんが、Lisp はシンプルな言語なので、じっくりと読んでください。
データ
Nu は通常の言語同様に数値や文字、文字列などが扱えます。ただし、Ruby等と同じくすべてのデータはオブジェクトで、Objective-C のオブジェクトシステムを利用しています。
代表的なデータは、
数値
整数(32bit)や実数(64bit)が扱えます。また数値は Objective-C の NSNumber を少し拡張したものです。
文字列
文字列はJava、Perl、Ruby のように "abc" と書きます。 ¥n のようなエスケープシーケンスも他の言語同様です。また文字列は Objective-C の NSString を少し拡張したものです。
シンボル
Lisp や Ruby同様、Nu も変数名や関数名などに使われる名前はシンボルというデータです。Nuでは数字や区切り記号以外の文字の並びはシンボル(変数名や関数名など)に使えます(注:区切り記号は ( ) ' ; #)。
例えば「abc」「a2」「a+b」「2a」はすべてシンボルです。
シンボルは Objecte-C にありませんので、Nu では NuSymbol というクラスが定義されています。
式
Nu は文法的には Lisp と同じですべてがS式です。Lisp ではS式を評価(計算)することが、プログラムを実行する事になります。
S式には、数値や文字列等のリテラルとシンボル、そして、それらの要素を並べカッコで括ったリストがあります。
リテラル
数値や文字列等のリテラルはその値を戻します。
$ nush % 1 1 % "abc" "abc"
シンボル
シンボルの場合は変数と見なし、その値を取得します。値の無い変数を参照するとエラーになります。説明が前後しますが、変数への値の代入は setオペレータを使います。
% (set x 12) 12 % x 12 % y NuUndefinedSymbol: undefined symbol: y %
リスト
(a b c) のようなリストの場合は a をオペレータ(Lisp では関数と呼ばれます)とみなして、b、c の値を計算し、それを引数にオペレータ(関数) a を使って評価します。
下は、足し算を行うオペレータ + に 1 2 という引数を渡しています。そして、結果の 3 が戻ってきます。
% (+ 1 2) 3
引数の部分はリストでもよくその場合は内側カッコ内から評価されます
% (* 2 (+ 1 3)) 8
当然、変数が入っていてもかまいません。
% (set x 5) 5 % (+ 3 x) 8
クオート(quote)
シンボルやリストを評価せずデータとして使いたい場合には、quoteオペレータを使います。
% (quote a) a % (quote (1 2 3)) (1 2 3)
quote はよく使うので次のように ' を使って簡単に入力できるようになっています
% 'a a % '(1 2 3) (1 2 3)
オペレータ
Nu の文法を今まで説明した事がほぼすべてで、制御構造や関数の定義もオペレータで行います。
いくつかのオペレータを説明します、
代入
既に登場していますが、setオペレータを使い変数(シンボル)に値を代入できます。
% (set v "Nu") "Nu" % v "Nu"
条件判断
下のコードは n の値が負の場合は minus、それ以外の場合は plus or zero と表示します。ここで < は値の比較オペレータで、puts はコンソール表示オペレータです。
% (if (< n 0) (then (puts "minus")) (else (puts "plus or zero")))
くり返し
下のコードは n が 0 より大きい間、n の値を表示しながら、n を1つづつ減らし繰り返していきます。
% (while (> n 0) (puts n) (set n (- n 1)))
オペレータの定義
Nu のプログラミングはNu言語でオペレータを定義する事です。当然プログラムもS式です。
下のコードは絶対値を求めるオペレータ abs を定義しています。
% (function abs (n) (if (< n 0) (then (- 0 n)) (else n))) ...結果は省略... % (abs -3) 3 % (abs 2) 2
ブロック
Lisp を始め最近の多くの言語は無名関数をサポートしています。Nuでは無名関数はRubyと同じようにブロックと呼ばれています。
下のコードは前の例と同様に与えられた n の絶対値を求めるブロックです
% (do (n) (if (< n 0) (then (- 0 n))(else n))) ...結果は省略...
ブロック自体はオペレータ(関数)定義ですから、リストの先頭に入れて通常のオペレターのように使う事ができます。カッコがたくさん書かれているので閉じカッコの対応する開きカッコを注意深く追ってください。
% ((do (n) (if (< n 0) (then (- 0 n))(else n))) -4) 4
先ほど説明した function オペレータで abs オペレータを定義するのは、ブロックと代入(set)を使って以下のように書いたのと同じです。
% (set abs2 (do (n) (if (< n 0) (then (- 0 n))(else n)))) ...結果は省略... % (abs2 -11) 11