RINEARN では先日、オープンソースの式計算ライブラリ「 Exevalator(エグゼバレータ) 」の最新版 Ver.2.2 をリリースしました。
今回から、新たに TypeScript にも対応し、Webブラウザ上で動作可能になりました! これにより、Webページ上やWebアプリのフロントエンド等でも、手軽かつ安全に、ユーザーが入力した式を計算できるようになりました。
実際にちょっと試してみましょう:
- 実演デモ -上記の「 計算実行 」ボタンを押すと、入力されている式と変数 x の値に基づいて計算が行われ、結果が表示されます。 この計算処理を内部で担っているのが、今回の更新で追加された TypeScript 版の Exevalator です。
以下では、もう少し詳しく掘り下げてみましょう!
Exevalator は、上で見た例のように、ユーザーによる入力値などの「 文字列の内容 」を、式として解釈・計算するためのライブラリです。 ユーザー入力値だけでなく、例えば「 設定ファイルなどから読み取った式 」を計算したい、といった場面にも使えます。そういう場面って、結構ありません?
そういった「 文字列を式として解釈・実行する 」という機能は、コンパイラ型の言語ではふつう標準ではサポートされていません。
また、インタープリタ型言語(スクリプト言語)では結構サポートされているものの、行える処理の範囲を細かく制限できないので、セキュリティ的な観点から実質的に使用NGな扱いになっている場合も多いです。 今回の TypeScript / JavaScript もそうで、一応は言語組み込みの eval 関数があるんですが、Webサービスでユーザー入力値を処理するのに使えるような代物ではないです(危なすぎる)。
つまり、「 ちょっと文字列として書かれた式を計算したい 」という場面って、いろんなプロジェクトでよくある割に、意外と手軽で普遍的な実現手段が乏しいんです。式の解釈処理を自作したり、もしくは何らかのスクリプト言語のインタープリタとかを引っ張ってきてバックグランドで呼び出したり、組み込んだりしなきゃいけない。
で、それなら、「ちょっと式を計算する」という事だけに焦点を絞った、移植性重視のシンプルなインタープリタを作っておいて、いろんな言語に移植しまくれば便利なのでは? という方針で開発しているのが Exevalator です。
実際に Exevalator は、ファイル一枚に実装されたいわゆる "シングルファイル" のライブラリで、プロジェクトのソースコードフォルダ内に放り込むだけですぐに使えます。
また、最新の Ver.2.2 の時点で Java、C#、C++、Rust、Visual Basic (.NET)、TypeScript の 6 つの言語に移植されていて、一般の幅広い分野をカバーします。
特に今回 TypeScript 版が新たに加わった事により、
という4つの大きなプラットフォームを全てカバーできるようになりました。
Exevalator はオープンソースのライブラリで、GitHub 上の以下のリポジトリでソースコードを公開しています:
使い方は上記リポジトリ内のドキュメントで詳しく解説しています。
ライセンスは、実質的な著作権フリーである「 Unlicense 」と「 CC0 」のデュアルライセンス(好きな方を自由に選択可能)で、改造も流用も自由に行えます。
さて、ここまではお手軽さとコンパクトさのみをアピールしてきましたが、Exevalator は実は計算速度もなかなか速いです。RINEARN ではいろんなインタープリタをもうかれこれ十数年開発していて、高速化のノウハウも結構あるので、Exevalator でもほどほどのバランスでそれを盛り込んでいるためです。
具体的には、同じ式の反復処理(変数の値が変わるだけなど)では、ベンチマークでの最大値で数億演算/秒(数百MFLOPS)くらい出ます。数値積分くらいなら一瞬で終わりますし、そこそこの規模のデータ処理にも耐えられます。
なお、式の形が毎回変わる場合は、構文解析コストがかかるため上記よりだいぶ落ちますが、それでも数万〜数十万式/秒くらいは普通に出ます。
「 文字列の式を解釈して計算する 」って、なんか ものすごく処理が重いイメージ がありますが、実際は上記の通り結構速い&軽いので、ぜひいろんな場面で気軽に試してみてほしいです!
さて、すでに述べた通り、今回の Exevalator 2.2 から、新たに TypeScript がサポート対象に加わりました。使い方は こちらのページで解説 しています。
で、「 そもそも TypeScript って何? 」っていう点についても少しだけ解説しておきましょう。
とはいえ、その登場の経緯からして、一方的な視点で安易に深堀りすると 血で血を洗う言語論争的な炎上になりかねない ので、ごく軽くイメージ的な話だけしておきます。うっかりナンセンスな事を書いてたらすみません。怒らないで… 怒らないで…
さて TypeScript について解説するには、まず土台となる JavaScript について解説しなければなりませんね。
JavaScript は、Webブラウザ上で動作するインタープリタ型言語(スクリプト言語)です。JavaScript のインタープリタは、Webブラウザ自身の中に組み込まれているため、専用の開発環境や実行環境が無くても、Webブラウザさえあれば動作します。
現在の Web ページは、Wikipedia のようなシンプルな記事ページだけじゃなく、「 ページを操作すると色々と複雑な動きをする 」ものも多いですよね。そういったページの動的な処理の多くを、JavaScript で書かれたプログラムが担っています。
JavaScript だけでも、それなりに本格的な Web アプリのようなものを作れてしまうくらいには強力な言語です(一線を超えようとすると、サーバー側でもプログラムを動かして連携させる必要がありますが)。
そんな JavaScript ですが、登場は結構古く、もう30年近く前になります。
広く普及して長く使われている言語の宿命なんですが、「 実は言語仕様のここがちょっとよくなかったかな? 」とか、「 最近の言語の設計だと、別のこういう書き方がトレンドになってきた 」とか、「 大規模開発だとこういう機能が欲しいが、なかなか言語仕様に採用されないなあ… 」みたいな点が沸いて積もっていきました。あと、シンプルに「 文法が好みじゃない 」みたいな派閥の母数も増えてきたり。
これはもちろん言語開発者が悪いわけではなくて、色々な用途で使われるまでそんな事わかりっこないので、まさに長寿の言語の宿命ですね。あと長年、ブラウザ上で動くコードを書くには実質 JavaScript 一択な状況だったので、そもそも上記のような声が積もりやすいという性質もあったのかもしれません。「よその言語に行ってくれ」ができないので。
で、JavaScript も仕様(ECMAScript)を進化させて対処はしてるんですが、それとは別に、いっそ JavaScript をベースにした新言語と呼べるレベルのものを作っては? みたいな方向も流行ったりしました。「JavaScript の代替(Alternative)」の言語達なので略して「 AltJS 」とか呼ばれたりします。
AltJS と呼ばれるカテゴリーの言語達は、みんなそれぞれ独自の文法でコードを書いてから、基本的にそれをコンパイラで JavaScript のコードに変換して動かします。主要ブラウザ全てにその言語に対応してもらうのは大変ですが、JavaScript に変換してしまえば、いま出回ってるブラウザ上ですぐに動くわけですからね。
さて、いよいよ TypeScript です。TypeScript も、上記の AltJS の流れの中で出てきた言語で、Microsoft が開発・リリースしました。以下が特徴です:
という具合ですかね。で、この TypeScript がかなりヒットして、普及してきています。
やっぱり JavaScript のスーパーセットにしたという点がポイント高かったんですかね? 使う時も、JavaScript の知識とノリを基本に、ちょっと堅くがっちり書きたい、もしくはデカいものを効率的に書きたい、という場面で向いている気がします。
反面、JavaScript に長年慣れている人は、特に小さいものをざっと書く時は TypeScript の機能が若干面倒に感じるかもしれませんね。それで色々省略しまくって、これなら素の JavaScript でいいや、みたいな。
とまあ、そんな感じの言語です。
最後に、実際に TypeScript で Exevalator を使う流れを、駆け足でざっと紹介しておきましょう。
まずPC に「 Node.js 」をインストールします。Node.js は、ブラウザ上ではなく、ローカルで JavaScript のコードを実行したり、開発を行ったりする際の基盤となる環境です。
続いて、ローカルの適当な場所に Exevalator のリポジトリを clone し、その中の「typescript」フォルダに移動します:
この「typescript」フォルダの中に、TypeScript 版の Exevalator や、サンプルコード、テストコード等が入っています。この中で実際にコンパイル・実行するために、必要な環境を構築します:
ここで「 --save-dev 」を付けているのは、このフォルダ内のみで使える形で環境を構築するためです(つまりフォルダ外の環境を汚さない)。
以上で準備は完了です。サンプルを実行してみましょう。まず最初のサンプル「 example1.ts 」です。これは以下のコードです:
// Exevalator を読み込む(実際は配置に合った相対パスを指定)
import Exevalator from "./exevalator";
// Exevalator のインタープリタを生成
let exevalator: Exevalator = new Exevalator();
// 式の値を計算(評価)する
const result: number = exevalator.eval("1.2 + 3.4");
// 結果を表示
console.log(`result: ${result}`);
コンパイル・実行します:
実行結果は:
この通り、式 "1.2 + 3.4" を正しく実行できていますね。
続いて、ちょっと複雑ですが実用を意識した例として、この記事冒頭で紹介したような、「ブラウザ上で動く簡易計算アプリ」のようなサンプルを実行してみましょう。
具体的には「 example6ex 」で、TypeScript のコードはこちら 、HTML のコードはこちら です。
ブラウザ上で動かす場合、複数の TypeScript ファイル(ライブラリ含む)を、まとめて 1 枚の JavaScript コードに変換してしまった方が色々と好都合です。そうしないとモジュール読み込み周りのややこしい挙動に悩まされます。
そのために、バンドラと呼ばれる種類のツールを使用しますが、いまの場合は esbuild を使いましょう:
これで、一枚化してコンパイルされた「 example6ex.bundle.js 」が生成されます。
あとは、「 example6ex.html 」をダブルクリックしてWebブラウザで開けば、上記が読み込まれて動作します。その様子は、この記事冒頭で紹介したやつ とほぼ同じです。
さて、今回のお知らせは以上の通りです。 今後も、Exevalator に関する続報は、このお知らせコーナーにて随時お伝えしていきます。お楽しみに!