こんにちは, @the_theorierです.
今回紹介するのはLISPと呼ばれるプログラミング言語を使って数式処理が出来る「labmda LISP」です.
LISPとは
LISPは歴史上初の関数型プログラミング言語で, 現在も利用されているプログラミング言語の最古のものの一つだそうです.
我々がよく使うC言語などと違い, ポーランド記法による対話型言語です.
我々が普段扱っている数式記法は「中置記法」と呼ばれ, 例えば 1+2 のような書き方です.
ポーランド記法ではこれが + 1 2 となります.
ポーランド記法では演算子などとの区別を付けるためにそれぞれの間に半角スペースを入れる手間が必要です(区切るために使用する記号をデリミタと言います, 今回は半角スペースですが別の場合もあります)が, 中置記法では間に入れた演算子がその役割を果たすため, 必ずしもデリミタとして間に追加する必要はありません.
その分ちょっとだけ面倒ですね.
LISPではここから更に括弧を付けます, つまり (+ 1 2) ですね.
"("の右, ")"の左にデリミタを付ける必要はありません.
より複雑な式を書こうとすると, 例えば中置記法での 1+(2*3) はポーランド記法では (+ 1 (* 2 3)) となります.
なんとなく分かりましたか?
lambda LISP の使い方
lambda LISP はその名の通りで LISP に準じた数式処理アプリケーションですが, 一部 LISP と異なる…というか"機能制限"のようなものがあるのでそれを含めて簡単に紹介したいと思います.
ガッツリ調べたかったんですが思いの外簡単には理解できなかったので不足な部分が多々あると思います.
起動画面
起動するとこのような画面になります.
とてもシンプルで, 下の「type expression」をタップするとキーボードが出てくるのでそこから命令を書いて実行します.
また一度実行したものを編集したり削除することは現時点ではできないようです.
四則演算
まずは基本中の基本である四則演算からです.
基本的な使い方は先程の通りで括弧つきのポーランド記法です.
(+ 1 1)
(- 1 1)
(* 1 1)
(/ 1 1)
半角英数字が基本ですから × や ÷ は使えません, それぞれ半角の * , / を使います.
また 演算子とオペランドがくっついた場合もエラーになります(それをまとめて演算子を見做してしまうため).
(+ 1 2 3)
(* 2 3 4)
(* (+ 2 3) (+ 4 5))
またオペランドはこのように2つ以上に増やしてもOKです.
組み合わせてより複雑な計算もできます.
しかし乗法 * と除法 / についてはダメのようです.
また, 除法では例えば (/ 7 3) とすると上の画像のように小数点以下が丸められてしまいます.
小数以下を表示するためには以下のどちらかで記法します.
(/ 7 3.0)
(/ 7.0 3)
つまり除数ないし被除数に ".0" を書きくわえるわけですね.
ここは本来のLISPとは仕様が異なります.
変数定義
(defvar a 2)
変数定義は defvar という演算子を用いて例えば上のように書き表します.
本来のLISPでは例えば
> (defvar a 2)
2
> a
2
となるんですが, lamba LISP では画像の通りで定義した変数値を表示はしてくれないようです.
> (devar a 2)
2
> (devar pi 3.1415926535)
3.1415926535
> (* pi (* a a))
12.566370614
上手いこと使うとこのように円の面積なども求められます.
関数定義
(defun ff (x y) (+ (* 2 x) y)))
関数は例えば上のように定義します.
defun 関数名 (変数) (式)
という構造ですね.
関係演算子
(= オペランド オペランド)
(< オペランド オペランド)
(> オペランド オペランド)
(<= オペランド オペランド)
(>= オペランド オペランド)
という構造になります.
真であるなら true を, そうでないなら false を返します.
(/= オペランド オペランド)
見ての通りで演算子 /= は使用できませんでした, 重要な関係演算子の一つなのに…
またこちらもオペランドは2つまでのようで, 3つ以上になるとエラーになりました.
ついでに not や nil も確かめたんですがこれらも使えませんでした.
ifとcond
条件分岐として一番使われるのが if ですが, ここでは使えないようです.
(cond (= 1 2) (+ 1 2) (- 1 2))
代わりに使用できるのが cond です.
cond (条件) (条件が真の場合の処理) (条件が偽である場合の処理)
という構造になります.
上の例では (= 1 2) が偽ですから (- 1 2) の方が実行されています.
使えない?演算子など
調べるには量が多いので一部断定できないものだったり, まだ他にもあったりしますがおおよそ「これはここでは使えなさそう」な演算子などは以下のようです.
/=
/< ( /<= )
/> ( />= )
mod
round
ceiling
abs
sqrt
sin
cos
tan
log
exp
expt
random
max
min
gcd
lcm
nil
list
もしかしたら文字が違うだけかもしれませんし用法を間違えただけかもしれません.
〆
ちょっと本来とは使い方が異なる感じもしますが, こういうのが好きな方にはお勧めです.
因みに一度実行したものは編集などは出来ませんがコピーすることは出来ます.
うっかり括弧忘れたりしてイラつく…みたいなのはプログラミングでは良くあることですね…コピー出来るだけでもありがたいです.
贅沢を言えば MuPad みたいに大きな数字などが扱えると嬉しいです.
どうやら演算結果が20桁程度を超えるとオーバーフローして滅茶苦茶な値を返すようです.
例えば (* 10000000 1000000000000) の結果が -8446744073709551616 だったり, (* 10000000 10000000000000) の結果が 7766279631452241920 だったりと明らかに間違っていますね.