見出し画像

Retro-gaming and so on

RE: プログラミング学習日記 2024/02/13〜

龍虎氏の記事(2024/02/21)に対するコメント。


気軽な気持ちで読み始めたが・・
 えっ・・?Racketのコードなのに動作が分からない。実行のコードも試してみてようやく理解したが・・クロージャ分かったつもりなってて全然分かってなかったわ〜・・さらに先があったのか (・。・;
 表現しにくいけど、こういう多段技みたいなのが出来るとは考えてなかった

面白いでしょ(笑)。
「クロージャが環境を閉じ込めて」、そしてクロージャを「返す」事を実現している。
また、これじゃないと「オブジェクト指向の仕組み」を明解に説明出来ない、んだ。オブジェクト指向言語の「オブジェクト指向の仕組み」が言語に組み込まれている以上、ソースコードを読まないと「どういった発想/仕組みで書いてんだ?」って全く分からないからね。
これこそLispの面目躍如で、長い間、それこそ「Lisp上で」オブジェクト指向を「研究出来た」原因なんだわ。マジでメジャーなオブジェクト指向言語が出る前からLisp使いの研究者は「オブジェクト指向の仕組み」を研究しまくっていた事、になる。オブジェクト指向の「構文」がなくてもオブジェクト指向の研究が「言語上で実現出来る」なんつー特性は、少なくとも70年代〜80年代を通じて、「Lispしか」持ってなかったんだ。
Lispはかつては「誰も実装した事が無いプログラムの実験場」と言う先鋭的な言語だったんだ(いや、今でもそうだけど、単に「誰も実装した事がない」って分野が無くなっただけ、だ・笑)。

ちなみに、このコード、原理的には、それこそポール・グレアムが技術野郎の復讐で「プログラミング言語の力の意味を問うた」アキュムレータの実装と全く同じなの。
単に、アキュムレータ自体が引数に従った条件分岐(しかもクロージャを返す)を抱えてるだけ、でね。
「ラムダがあれば何でも出来る」と言ったSchemeの主張(っつーか、正確にはオリジナルのSchemeの開発者、スティールとサスマンが書いた論文、「ラムダ: 究極のメニュー命令文」と言う挑戦的なタイトルにその意図が見て取れる)の内訳の一つに過ぎない、んだ。

なお、実の事を言うとSICPでは「オブジェクト指向」の仕組みを解説しながら、同時にポジション的には「オブジェクト指向」に対しては反対の立場を取ってるのね。「状態を保持する」事に対して疑問を呈してる
だからどっかで、Javaのユーザーだったかな、がSICPを読んで、「関数型プログラミングへと恣意的に誘導してる!」って批判してる記事があったような気がする・・・・・・失念したが(笑)。んで、確かにJavaプログラマにとっては死活問題だ(笑)。言語の根幹、つまり「アイディア」を否定されたらシャレになんない。


 で、Python版も拝見する。まずNonlocalを調べて・・DepositMoneyとWithdrawalMoneyは補助関数でDispatchがメインとなってクロージャを返して引数待ちの状態になっとると。で、Msgによって場合分け、それぞれの補助関数というか補助クロージャを呼び出して引数待ち状態になると・・ほぇ〜・・面白い。

面白いでしょ(笑)?
Pythonもローカル関数が使えて、関数がファーストクラスオブジェクトだから「オブジェクト指向の原理的な仕組み」を学ぶには良い言語だよ(笑)。

そして書かれている通りでクラスのありがたさが良く分かりました〜

でしょ(笑)?
原理的な「オブジェクト指向の仕組み」を把握して、かつ「毎回毎回こんなこたぁ書きたくねぇや」ってなった時に「クラス」と言う「便利機能」のありがたさが分かる(笑)。
そうじゃないとね(笑)。
まぁ、オブジェクト指向が良い/悪いって話がある事はあるんだけど、一方、「どうしてプログラム言語に機能Xがあるのか」っつーのは、単に便利だから、としか言いようがない(笑)。
原則的に、「ユーザーを混乱させる為に✗✗と言う使うのが難しい機能を搭載しました」ってこたぁあり得ないわけだからさ(笑)・・・・・・いや、Schemeの継続を除けば(笑)、大体のトコ、そんなトコじゃないの?
フツーの人は「嫌がらせ」で新機能を搭載するわけじゃなくって、あくまで「親切心」からその機能の搭載を決定するわけだからさ。

 正確には今朝拝見したんですが・・あ、やっぱり問題ありましたか・・

うん。
いや、ごめんね。今からこの本やろう、って状況だったのに、アレ書いていいのかどうかちと迷ったんだよ。
ただ、言い訳させてもらえば、龍虎氏はもはや「プログラミング中級者」以上じゃない。ど素人じゃないわけで。僕がアレ書いたトコで「自分で何とか出来る人だ」って思ってたのね。
それくらい「Lispを学んだ」って事に対しては絶大な信頼性があるわけ。
むしろ、本当のPython初学者相手とかにさ。やっぱ「何が良くて何が悪いか」伝えとかならんだろ、と。
いや、マイナーブログだから僕が何書いたトコで変わらんだろうけど(笑)。
一応、そういう意味です。

以前からコードの書き方参考にならない!と指摘していただいてたんで「せめてコードはリスト内包表記とかで書こう」と思ってたんですが

うん、多分リスト内包表記云々、って辺りでそう考えたんじゃないのかな、とは思ってた。
悪いね、逆に気を使わせたようになっちまったかも。

そもそものコンセプトがヘンテコリンだったとは・・すでに3分の1くらい進んでるのに、この調子で高校数学を網羅出来るのか?とも思ってたんですが。

あ、やっぱり(笑)?
なんか完遂したOCamlの「プログラミングの基礎」に比べると、途中で中断したのが異様に早かった気がするんだ・・・多分直感的に「何だこれ?」って龍虎氏自身も過去、感じたんじゃないかな・・・とか予想してはいた。
何か数学の理論自体はいいんだけど、「計算を電卓(Python)で確かめるだけ」になってるじゃん。ホント「マトモなプログラムと言えるプログラム」って殆どないのよね、この本。
言い換えると、Numpy/Scipyの「へなちょこなユーザーズガイド」っつーか(笑)、「しょぼいリファレンス」っつーか(笑)、いや、その「機能を調べる程度」だったらリファレンス読めば済むや、程度の事しか結果「総体的」には書かれてない本なんだよな。

余計な出費をさせてしまいまして申し訳ないですm(_ _)m

いやいや全然。そこは気にしないで。
っつーか、「ブログの連載記事のネタになるかも」ってかなり厭らしい期待してたんだよ、正直なトコ(苦笑)。
単に「連載記事にする程の本じゃなかった」ってだけで(笑)。ホント、そこは私欲です(笑)。
だから余計怒ってた、と言う(笑)。「期待はずれじゃねぇか」とか(笑)。
もっとも、勝手に期待してた俺が悪い、って言えば悪い(笑)。

いやつまりさ。以前から「数値スクリプトは簡単」「遅延評価なんかの機能を試す分には数値計算がトピックとしてはいい」って言ってたでしょ?
だから、そういうアイディアを見せる「叩き台」として丁度いい本じゃないのか、って期待してたわけ。全然違ってたけど(笑)。
龍虎氏に自覚あるかどうか知らんけど、ある意味僕らってのは「プログラミング言語の理論」の最前線にいるわけ。Lisp(及びその他の関数型言語)を使ってる、ってのは自ずとからそういう意味になる。
でもさ。「遅延評価が良く分からん」とか「使うの怖い」とか言うのって当然なんだよ。
要は「具体的に何かに適用する」ってなってもその例を思いつかないわけじゃない。
「ある」のは「ある」って知ってるけど、じゃあそれを現実の問題に「どう適用するんだ」と。
要は練習出来る遊び場、ってのかな、そういうのが無い、っつーか探しづらい。
実際使う場がなければどうしようもないわけでしょ。
それこそ「机上の空論」ってヤツで。

ちょっと前に書いたハフマン符号と言うか、foldTree/unfoldTreeの話、ってのもそういう意味なのね。「数値しか扱えない二分木生成なんてどんな意味があるんだ」みたいな。
でも「理論」が出てくる時、ってのは、それは当然「数値対象」であるわけよ。もうガチガチの「数値相手」のモノになる。
例えば、SchemeのSRFI-41で、

> (require srfi/41)
> (stream-iterate (lambda (x) (+ x 1)) 0)
#<stream>
>

とかやってさ。#<stream>には無限長の整数列が入ってます、とか言うのって「理屈としては」面白い、たぁ思う。そのまんまだ。
でも現実世界に於いて僕らが興味ある、ってのはこういう事じゃん?

例えば何かの関数(what-kind-of-proc?)を使えば河北彩花の写真からFANZA AV女優ランキングの無限長のストリームが作れるのか、とか(笑)。
あるいは、なんかのノベルゲームとかアドベンチャーゲームを作るとすんだろ。
で、そのシナリオが、だ。

> (define *scenary* (stream-iterate (lambda (x) some-script-generating-logic) "あたし、亜美。ヒロシって言う素敵なお兄ちゃんがいます。でも血はつながってないの。"))

みたいなカタチで、baseを与えれば「延々と終わりのないシナリオ」を生成して、永久にプレイできるゲームを作れるのか、とか。
そっちじゃん?興味の対象は。
もちろん、こんなんは「成り立たない」って知っている。
これは「アタマが硬い」かどうか、って問題じゃなくって、現実問題としてプログラムと言うものが「データをフィルタリング/加工するモノ」って前提な以上、「現実に使えるデータを生成」出来なければ単なる画餅だろ、って話なのね。
言い換えると「いくら無限長のデータを生成出来る」とは言っても、その「データ」が数値「だけ」だったらとてもじゃないけど現実の問題に適用出来ない。
プログラミングは「理論だけ」ではどうしようもなくって、遅延評価とかに対して「画餅だろ」ってあんま旨味を感じない人が多い、ってのは要は、上で書いたような事を「直感的」に分かってるから、なんだよな。

とは言っても、遅延評価、あるいはPythonのイテレータ/ジェネレータは強力ではある。そして「どっかで絶対使いどころがある」筈なんだ。
っつー事は「来たるべき時に備えて」概念だけ、じゃなくって「使える」準備はしとかないとならない。
じゃあプレイグラウンドはどこだ、って考えると、やっぱ「数値計算」しかないわけよ。練習しとくならそこしかない。
まぁ、そういうのがあって、「Pythonで学び直す高校数学」があれば、その辺の「使い方」を上手くブログの記事として説明出来るかな、とか期待してたわけね。
結果は期待はずれだったんだけど(笑)。


 そして例の東大気分が味わえるであろう数値計算の本も早速購入しました。まあ、メルカリなんですけど。数値で色々と遊ぶのはコッチでやろうかと。

あら、早いのね(笑)。
男性相手のほめことばじゃねぇか(笑)。


さて、じゃあちと軽くMATLAB(Scilab)の説明をしようか。
Lispは「リストが基本の」プログラミング言語だった。
一方、MATLABは「行列が基本の」プログラミング言語なんだ。そもそもMATLABはMatrix Laboratory(行列研究所)と言う意味で、LispのList Processingとのネーミングの対照を考えても面白い存在だと思う。
Lispの場合、リストを行列に見立てたとしても

(+ '((50 40) (10 10)) '((30 100) (20 15)))

と言うような計算は成り立たない。これはPythonのような言語でも同様だ。
一方、MATLAB(Scilab)は、こういう計算を、数学的規則に従って自然と行うように設計されている。

-->[50, 40; 10, 10] + [30, 100; 20, 15];
ans =


80. 140.
30. 25.

こういう「行列に関する演算」に特化した基本設計になっているのがMATLAB(Scilab)の特徴なんだ。
見たら分かるけど、そもそも、通常のプログラミング言語に於いて、「配列」とか「リスト」を使って2行2列の行列の記述をするのはメンド臭い。「配列の配列にする」とか「リストのリストにする」とかせんとアカン。
一方、MATLAB(Scilab)の場合、2行2列の行列表記さえ簡単なんだ。横に要素を並べる場合はカンマ区切り、縦で「行が切り替わる」時にはセミコロンで記述する。
従って、非常に簡便に「行列を表現出来る」ようになっている。カッコ塗れにならなくていいんだ。
また、出力も、僕らが期待するような「数学的に良く見る」行列のスタイルになっている。
行列を基本として扱う、と言うプログラミング言語が「行列をたくさん使ったプログラムを書かねばならない」業界だと如何にウケてるのか、この例だけでも分かるだろう。
以前別のトコにも書いたけど、そもそもコンピュータ自体が「行列演算が苦手」なトコに「クソ面倒臭い行列演算プログラム」を書くのが如何に苦行か、と(笑)。
繰り返すけど、MATLAB(Scilab)は確実にニーズがある、ある意味「特殊分野」の鉱脈を掘り当てたわけだ。如何にその分野で「必須の」ツールになってるのか、ってのが分かると思う。
また、「Pythonで高校数学を学び直す本」に対して、まるで「GNU Octave使った方がマシだろ」って皮肉を言ったように聞こえたかもしれんけど、マジなんだよ。あの程度のプログラムだったらPythonにNumpyやらScipy導入するよりMATLAB系のプログラミング言語を使って記述した方が遥かにラク、なんだ。

例えば「Pythonで学び直す高校数学」のリスト5-1。図形の対称移動だな。
そのコードはこんな風に書かれている。

import numpy as np
import matplotlib.pyplot as plt

# 三角形 ABC の頂点
p = np.matrix([[1, 3, 3, 1], [1, 1, 2, 1]])

# 変換行列
A = np.matrix([[1, 0], [0, -1]])

# 変換
p2 = A * p
print(p2)

# 描画
p = np.array(p)
p2 = np.array(p2)
plt.plot(p[0, :], p[1, :])
plt.plot(p2[0, :], p2[1, :])
plt.axis('equal')
plt.grid(color = '0.8')
plt.show()

一方、Scilabだとこうだ。

// 三角形ABCの頂点
p = [1, 3, 3, 1; 1, 1, 2, 1];

// 変換行列
A = [1, 0; 0, -1];

// 変換
p2 = A * p;
disp(p2)

// 描画
plot(p(1, :), p(2, :), 'c'); // 第3引数で色を指定
plot(p2(1, :), p2(2, :), 'm');
a = get("current_axes") // 軸の情報を得る
a.data_bounds = [-1, -3; 5, 3] // 軸を使って描画範囲を指定
xgrid(1, 1);

Python + Numpyだと描画する為に行列から一旦二次元配列に直す、なんてやってるけど、Scilabでは必要ない。そもそもマジで「行列を扱う為の」言語処理系なんで、その辺煩わしさがない。
plot関数に関して言うと、第3引数を使って色指定せんとScilabは地味に描く(笑)。一方、pyplotlibは自動で色を振り分けるね。この辺はpyplotlibの勝ちかな。
あと、Scilabはとにかく「詰めて」描こうとすんのね。ギリギリまで詰める。だから余裕を持って描きたい、って場合は軸情報を取ってきて、描画範囲をこっちで指定せんとアカン。その辺はちとメンドイ。
ただ、「適当に描いてくれ」って意味ではScilabの方が勝手に色々とやってくれる、ってカンジ?オブジェクト指向で良くあるような、何とか.show()なんかもねぇし(笑)。直球勝負ならScilabだろ、ってカンジ。


あと、良くあるスタイルで、「配列やリストの要素にアクセスする際」、

a[i]

とか書くのを良く見かけるけど、Scilabだと丸括弧を使って

a(i)

って書く辺りも特徴的だよな。
そして要素を0から数えない(笑)。1から数える、とこれまた昨今では珍しい形式なんだ。

さて、軽く関数定義にも触れておこう。
これが多分一番衝撃的だろう。ビックリすると思う。

function [result] = dec2bin(target)
 amari = list();
 while target ~= 0
  amari(0) = modulo(target, 2);
  target = floor(target / 2);
 end
 result = amari;
endfunction

さて、関数名は「十進数から二進数への変換器」って意味でdec2binなんだが。
そもそも

function [result] = dec2bin(target)

って書き始めは何なのか。代入してんの?と。
dec2binが関数名、って事はtargetがその関数の引数なのは薄々と分かるだろう。
じゃあ左辺は何やねん、と。
functionってのがSchemeで言うdefineとかPythonで言うdefにあたる、ってのはこれも何となく分かるだろう。
じゃあresultって何や、と。

そう、実はプログラミング言語の中には、returnを使用せず、なんかの値が返る事を「なんかに代入する」事で表現する言語があるんだな。仮引数に対して「仮返り値」とでも呼べばいいのか(笑)。

function [仮返り値1, 仮返り値2, ... ] = 関数名(引数1, 引数2, ...)

多分この形式の言語は初めてだから面食らうと思う。実はPascalがこの形式なんだ。
あと、isamさんに教えてもらったんだけど、Visual Basicも基本そうなんだってさ。
んで、Scilabはもう一つ特徴がある。ブロックを明解に書かなアカンのな。
例えば関数定義functionで始めると定義終了にはendfunctionと書く。
  • whileで始まったブロックはendで終わる。
  • forで始まったプロックはendで終わる。
  • ifで始まったブロックはendで終わる。
ブロック終了をendで終える、ってのはRubyで有名だけど、Pascalもそういう形式で、Scilabもそうなんだ。
今まで「明示的にブロックを終えなければならない」ってのが無かったんで(Lispはカッコだらけだし・笑)、これは初めての形式だと思う。
あと、細かいトコ言うと、否定をチルダ(~)で書く、ってのは珍しいね。

これらがScilabの大きな特徴かな。
なお、リファレンスマニュアル的なヘルプ、ってのが日本語にも訳されてるんで、機能を調べるのは比較的簡単だと思う。

アマゾンで日本語版が売られてるからか?

そうなんだよね。僕も最近気づいた。
10年以上続いたサイトがキンドルのせいで無くなっちゃったんだよ(笑)。
だからもう、Pythonを良質なWebサイトでタダで勉強する、ってのが不可能になっちゃった。
でも簡易リファレンス、っつーか機能解説集的なThink Pythonの日本語版は生きてるんで、龍虎氏ならコードを読んで詰まった時にはこれから調べればいいんで大丈夫だとは思うんだけど。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最近の「RE: プログラミング学習日記」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事