「#1 Java API は使えるの?」 < Viivi Blog < Viiviの小部屋 < 入り口/Entrance


[NOTE]
This article is written ONLY in Japanese.
I hope you can read the contents through one of the surprisingly advanced latest machine translators,
such as Google and DeepL.


#1 「Java API は使えるの?」

ほんとは blog のはじめのほうの記事として, Scheme が浸透していない初心者の方に向けて Scheme プログラミング言語の紹介を 書くことを考えておりましたが, 急遽(きゅうきょ),専門家のみなさまに向けて書かせていただくことに変更しました.
どうやらここを訪れていただいている方々のほとんどは, 僕が期待していたような Little Schemer のみんなではなく, 筋金入りのモノホンでガチな Real Schemer の,さらに上層部の方々らしいからです.
どうか震えながらキーボードを打つ僕の姿を想像しながらお読みください.

あちこちに言い訳として書いていますが,僕は情報科学や情報工学の専門家ではありません.
全くの趣味として Viivi を書き始めたころから, 最初に Shibuya.lisp で Gino(仮) の概要をお話しさせていただくまで, 閉じた世界で自分が作りたいソフトウェアを目指して設計/実装を続けてまいりました.
完全に何もない 0 の状態から,僕なりの R5RS 評価装置を組み上げています.
最初のころだけ R5RS の理解のためにいくつかの処理系の挙動は確認させていただきましたが, 処理系の実装内部は一切見ていません.

本物の Schemer のみなさまにお会いしたりネット上で交流させていただく機会を得るようになって, ひとつ驚いたことがあります.
それはどの方からも必ず
「Java API は使えるの?」
「Java API を使えるようにしてほしい」
というご質問やご要望をいただくことです.
どうやら本物の Schemer の方々には
「Scheme 言語で Java-API を自由に操(あやつ)りたい」
という共通のテーマがあるらしいです.

世の中にはほかにも JVM 上で動く Lisp というものがたくさんあって, それらは Java-API を自由に使えるようになっているらしい.
僕はほかの処理系に全く興味がありませんので,それらについての情報もあやふやです.
この前提のうえで, Viivi とほかの処理系との違いを説明させていただきながら, Java-API についての Viivi の立場をお話しさせていただくことにします.
「ほかの処理系」と毎回書くのは面倒ですので, 以下では OILJ ("Other Implementations for Lisp on JVM" の略) と記述します.

ひとことで言ってしまえば,OILJ と Viivi との違いは 「JVM に対する抽象性」の違いです.
JVM に対して,OILJ は抽象性が低く,Viivi は抽象性が高いのです.
もうこれだけでかなりの方はおわかりかと思います.

おそらく OILJ は JVM にゴリゴリに密着した実装になっているんだと思います.
OILJ の処理系内部では,きっと JVM の object-data をそのまま(または近い形)で保持していて, その操作も JVM instruction と1対1に対応させて行っているのでしょう.
「JVM を動かす」という意識で実装されていますから,すべてが JVM に特化されているわけです.
この場合,Java-API は処理系の自然な延長にありますから,それを使うことは非常に簡単なはず.
もうひとつの利点としては,処理速度が速くなるであろうことが挙げられます.
余計なことを一切しませんから,まさに Scheme 言語によって JVM を動かせる.
いかにもプロの方々がツールとして使うための実装方針であるように思います.

一方,Viivi はそんなガチ実装とは真逆の,いわば「お花畑」実装です.
ふわふわと宙に浮いたところで R5RS だけを夢見て実装されています.
JVM をプラットフォームとして選んだのも,いわば「たまたま」で, 特定のハードウェア向けに書くより多くの人に使ってもらえるかもしれないと思ってそうしただけです.
JVM そのものについて,申し訳ないのですが,特にこだわりはありません.
「JVM ははるか下のほうにあるみたいだけど,あたしにはよくわかんないわ」的な.
そのかわり Viivi の手がもうすぐ届きそうなところに R5RS は輝いています.
あとちょっと手を伸ばせば(bug をつぶせば),完全に R5RS 互換になれると信じているのです.
例えば Viivi では continuation を全く制限なく使うことができます.
生成する continuation の個数やタイミング,再開する continuation の個数やタイミングには 全く制限がありません.
continuation は「制御された GOTO (controlled GOTO)」というような言われかたをすることがありますが, まさにプログラムのいろんなところからいろんなところへぴょんぴょんと 自由にジャンプすることが可能です.
(にもかかわらず,いわゆるスパゲッティプログラムには絶対にならないというのが continuation のすごいところ.あ,ご存知でしたね.釈迦に説法とはまさにこのこと.)
R5RS の機能を100%実装するために,Viivi ではデータ構造や処理を独自に定義しています.
それは JVM のデータ構造や処理とは別モノと言っても良いと思います.
(もちろん,最終的には同じ JVM 上で動くわけですから, 結果として JVM instruction に対応しているものもあるとは思いますが.)
この実装方針だと,ターゲットのプラットフォームに制限されずに R5RS の夢を見ることができます.
Viivi として抽象化された層に R5RS 機能を実装していくだけのことですから.
ターゲットのプラットフォームにこだわる必要はないのです.
したがって JVM 以外の Object-Oriented なプラットフォームに移植することも可能です.
たとえば C# やそのほかの OO (Object-Oriented な) 言語による書き換えや, 各種ゲーム機などのハードウェア に移植することも極端に難しくはないと思います.
(ただし条件としては Viivi が使っている基本的な Java API と同等の API が用意されていることと, Exception-handling が使えることが挙げられます.)
原理的には Viivi 層と プラットフォームの API とのやり取りの部分を書き換えるだけで移植は可能なはず.

この実装方針における欠点としては,まず処理速度が挙げられます.
プラットフォーム (いまの場合なら JVM) の instruction を1対1でたたくわけではなく, いろいろ余分な処理を行っていますから,当然遅くなります.
ここでも言い訳をさせていただけるなら, Viivi はまだ R5RS 完全互換に向けて修正を加えている段階にありますので, 処理速度に対する最適化のようなことを「一切」行っておりません.
ですから現段階で「こりゃ使えんわ」と投げ出さないでおいていただきたいのです.
最適化が完了したあかつきには,それはもう, 爆速処理系としてみなさんを驚かせるに違いありません (そんなわけないかw).

さて,ようやく Viivi における Java API の使用についてです.
たとえば処理の末端で使われることが多い I/O 関係の API というのは 比較的単純なデータの受け渡しを行うものが多いです.
たとえば文字列を外部から受け取ったり,外部へ出力したり.
整数値,浮動小数点数値であっても同様ですね.
このような基本的なデータの受け渡しを行う API は Viivi の内部から簡単にアクセス可能です.
事実,Viivi では Java API のひとつである Socket-class を使って, ネットワークポートをあたかもファイルであるかのように扱えるようにしてあります.
(後述するように,このような設計は初心者に向けた方針に基づいています.)
それを閉じた実装にせずにユーザに公開すれば「Java API が使えた!」となるのかもしれません.

これとは異なる例として,たとえば Scheme プログラムの内部から Swing API を使って画面上に JFrame の窓を表示させたいと考えたとしましょう.
JFrame には位置や大きさや閉じる方法などのさまざまな属性が付随します.
これらをまとめて扱うには,JFrame という class や instance を「そのままの形で」 Scheme 処理系が扱える必要があります.
もし Scheme 処理系の内部に Swing の object-design と少しでも異なる扱いがあると, API 呼び出しの際にそれらの間でデータ構造や処理についての変換が必要になり, とても非効率的です.
JFrame という窓枠だけでなく,その窓枠の上に載っている部品や, そのそれぞれの機能についても JVM で定義されたままの形で扱うことができなければ API 呼び出し時の処理がたいへんになることは想像に難しくありません.
一般的な Java API が完全に自由に呼び出せるようにするためには, Java API と受け渡しする可能性のあるすべてのデータを Scheme 処理系も同じ形のまま扱えるようにする必要があるわけです.

さてそうなってくると,話はデータだけの問題ではなくなります.
いま扱っているデータの object-instance がどの class に属するものなのか, その class はどのような継承関係の下に存在しているものなのかを知る必要があります.
アクセス制限 public/protected/private の区別がつかなければ困る状況も生じるでしょう.
プログラミングを行う観点からすれば,それらを知るだけでは不充分で, 積極的に操作できることが要求されます.
class 構造を記述するための構文, class の継承関係を記述するための構文, アクセス制限のための構文, class 内のメンバを参照するための構文, 外部から public-procedure を呼び出すときの構文などなどが必要です.
しかしご存知のように,このような object-oriented な機能や構文は 少なくとも R5RS では定義されていません.
Scheme 言語に JVM の class や instance についての object-design を組み込んだ, いわば「JVM-Object Scheme」とでも言うべき言語仕様を定義しない限り, 完全に自由に Java API を呼び出せる実装というものは不可能だと考えています.
一人で考えた結果このような結論に達しましたので, Viivi では現在, 一般的な Java API をユーザに使えるようにする機能は 一切実装してありません.
(上で述べたネットワークポートの例のように,API として外部に見える形ではなく, Scheme の言語構造や IDE の中から使えるようしたものは少なからず存在します. garbage-collection button などはその例でしょうか.)

以上は Scheme/Viivi 側からの見かたを書きましたが, JVM/OILJ 側から見ても同様のことが言えます.
JVM の構造や機能に忠実な Scheme 実装系を作ったとしても, R5RS 互換だと主張する限り,JVM にはなくて R5RS だけにある機能も実装する必要があります.
分数型数値や複素数型数値 (これらは必ずしも必須ではないらしいけど), continuation,(closure?,) multiple values,promise/force など, 非 JVM の仕様を備える必要があるわけですから, 必ずどこかである程度の不整合や制限を受け入れる必要はあると思います.
要は,Scheme 処理系の設計でどちらが良いとか悪いとか, 優れているとかいないとかを議論することが重要なのではなく, どのような特徴を良しとするのか,どのような目的に使われるのかという項目によって 選択されるべきものであると考えています.

では Viivi の使用目的は何か.
僕はいわゆる言語オタクで,いろんなプログラミング言語を試してきましたが, Scheme ほどおもしろいプログラミング言語はありません.
一言で書くならば,「algorithm を感じる」プログラミング言語なのです.
これは algorithm がわかりやすいと言い換えることができるかもしれません.
S式でのソースコード記述は,最初異様な感じではありますが, これがある瞬間,すばらしい記述形式だと気づいて涙することになります.
この感動を初心者のみなさんにも是非体験していただきたいと思っています.
初心者の方が抵抗なく使えるように Viivi IDEVITSE を実装しました.
評価過程を対話的に可視化できるので初心者のみなさんにもわかりやすいのではないかと思っています.
たとえ Scheme プログラミングを教えてくれる先生がいなくても, 好きな教科書を一冊選んで,そこに書かれているサンプルコードを入力すれば, Viivi が個人の専属 tutor となって, そのコードが評価されていくようすを 1 ステップごとに示します.
一般的なプログラミング習得を目的とする場合, どんなプログラミング言語を使うよりも, Viivi を使って Scheme プログラミングを自習するのが 最短距離なのではないかと本気で考えています.
もちろん自習に限りません.
教室での授業などでお使いいただけば,先生のご負担を軽減するまさに本来の tutor として機能します.
最初は初心者だけを対象に考えていましたが, 動くようになった Viivi IDE / VITSE を見てみると, (もしこれが完成すれば,の話ですが) 仕事で Scheme プログラミングを行っていらっしゃる方にも debugger としてお使いいただけるのではないでしょうか.
評価過程の対話的可視化環境は,問題の特定や修正を行う目的に対しても作業効率を上げるはずです.
速度が遅い Viivi ではありますが, このような学習用,開発用にだけ使うことにして, 実際の本実行には高速な他の処理系をお使いいただくようにすれば 効率の良い学習/開発が可能になるはずです.
これも R5RS という共通の標準仕様が存在する Scheme の世界ならではの話だと思います.


「#1 Java API は使えるの?」 < Viivi Blog < Viiviの小部屋 < 入り口/Entrance


ご連絡方法

2022/03/12 開設
Copyright(C) 2003-2022 ilma <ilma@viivi.io> All rights reserved.