見出し画像

Retro-gaming and so on

RE: プログラミング学習日記 2022/09/12〜

星田さんの記事に対するコメント。

> 2022/09/26

 えっ!組み込みの関数を一時的に上書き出来るのか!関数名が被るとエラーが出ると思ってました。

そもそも、それ以前に、実は一般的にLispは「一時的」じゃなくとも上書きO.K.の言語なの(笑)。
この例の場合、「一時的」になってるのはあくまでトップレベル環境じゃないから。
でもトップレベルだと「一時的」じゃなくなる(もちろんインタプリタをリロードすれば元に戻るんだけど)。

それ以前に恐ろしい事実を。そもそもLispには予約語と言う概念がない。それが意味するのはどんなシンボルでもユーザーが再定義する自由がある、ってこった(※1)。
実際、例えばSchemeだとR7RSで索引からででも引いてみようとしても予約語、と言う単語がない。単語がない以上定義がない。実装者が参照すべきリファレンスなのに全くそういう概念が無い、って事を言外に言っている。
つまり、R7RSで定義されてる全シンボルを任意にユーザーが自由に再定義しちまって構わん、って事になる。ある意味これほど危険な言語はないんだ。

例えば、Pythonなんかで予約語の一つであるifを再定義しよう、なんつーと当然怒られるわな。文法違反、とか言って。



ところが、Lispだとこれが出来ちまうんだ。



なんでLispはこんなに危険な言語なんだろう。
一つの理由として、ポール・グレアム流に言うと

「Lispはハッカーの為の言語であり、ハッカーが"やりたい"となったらハッカーの自由を尊重し、どんな阻害もしない」

と言う哲学を持ってる、って事だ。

言語設計者は、ユーザを自分のミスから守ってやらなきゃならないようなまぬけではなく、 設計者が考えもしなかったようなことを実現できる天才と考えた方が良いと思う。 何をしようがまぬけは自分の足を撃つのだ。他のパッケージの変数を参照するミスを 防いでやることはできたとしても、問題設定を間違えた悪い設計のプログラムを 延々と書き続けることから救うことはできない。 


余談だけど、この辺の「シンボルの再定義」の云々で出てくるのがマクロに於けるシンボルの衝突だ。
これに付いて、かつて、とあるCLerと川合史朗さんの間で議論のやり取りがあった、って事を記しておこう。

必要な措置だったんですねぇ

うん、まぁ、UIをどう設計するか、ってのもあるんだけど、PaizaもREPLとして直接入力出来ないようになってるでしょ?あくまで「端末みたいなヤツの表示」に留めてる(だからdisplayが必要になる)。
なお、覚えてるか分からんけど、特に剥き出しのREADは危険だ、ってのはLoLにも書かれていると思う。
だからこそWeb系のツールは、ローカル環境に比べるとどうしてもインタラクティブ性が落ちるわけね。

まあ問題は倉庫番をクリアするためのアルゴリズムってのが全く思いつかないことなんですが。

これ、実はアメリカの大学の一部では研究対象になってるみたい(笑)。
いわゆる「探索」ってのは言い換えると力技なのよ。「色々やってみて」下手したヤツは捨てて、上手く行ったヤツだけ採用する、みたいなのね。
だから必ずしも「探索で解けない」とは言わないんだけど、有限時間内に解けるのか、とか、そういう話が必ず出てくる。この辺は実は数学の話なの。
例えばさ、「将棋/囲碁/チェスを勝つように打つ」アルゴリズムってのは言い換えると「将棋/囲碁/チェスの必勝法がある」って意味なんだよ。
ところがこれは見つかっていない。今コンピュータがやってるのは原則、コンピュータが今は速度が速くでメモリがたくさんあるんで、「あらゆる局面の進みを探索木として表現して」総当りなんだ(笑)。人間で言うと「アタマの悪いやり方」なんだよな(笑)。
まあそんなわけで、実は「倉庫番の必勝法」ってのは見つかっていない。今のトコ「無い」って事だよね。探索に頼んないとならないわけだから。
言い換えると、「必勝法がない」からゲームとして成り立ってるわけだけど。

>> 2022/09/27

 あ!なるほど!! ん?と言うことは停止条件の後に関数の実行も可能ということでもあるのか・・

うん、それは当然だね。停止条件内で関数を実行してからreturnするわけだから。

もしかしてパターンマッチングか何かを使って常に適切な終了処理をするようなend関数(仮名)を作れたりするんだろうか?ちょっと今度試してみよう。

うん、発想がいい。
ただ、それはLispで言うと関数と言うよりマクロになるかな。
それで、過去、星田さんが考えたような事を考えて実行して出来たのが平たく言うと例外処理なんだ。
実はこの時点で、星田さんは例外処理の基本コンセプトを掴んだ、って事になる。


教科書を読んでいて、へぇ〜となる。つまりコレって無限ループするかどうかは「やってみないと分からない」って事かな?それでメモリを使い切るまでとかタイムアウトでエラーが出るようになってるのか(推測)。

全くその通り、ドンピシャだ。



Fold-leftだったらLmabdaの仮引数の順番が入れ替わると。

 後はおなじみのSUMをFold-rightで・・なんだけど、自作版はリストと初期値の場所が定義で入れ替わってるので注意という事ですね

いや、そこはちと誤解があるかも。
fold-leftfold-rightの違いは、「リストを(結果)左から処理していくか、右から処理していくか」の違いであって、lambdaの仮引数の順序は関係ないです。
ポイントは、Schemeに於いては、fold-leftfold-rightのラムダ式の引数順序のおかしさの理由は、可変長引数としてリストを複数取れるので、そういう引数の順番になっている。実装上の理由なんだ。
一方、OCamlのfold系関数は、請けられるリストは単一なの。つまり、引数としてリストは一つしか取れない(※2)。だから実装上、関数部分の引数順序と初期値、リスト引数の順番は同一で構わないわけ。
そういう意味ではOCamlでのfold系関数の書式とSchemeでのそれは違うんで、多分混乱したんでしょ。

※1: ただし、ANSI Common Lisp処理系のSBCLなんかは、ビルトイン関数やマクロを再定義しようとすると、警告を発したりする(が、禁止はしていない)。

※2: あとは、リスト引数が二個取れる亜種が存在するだけ、だ。OCamlではリスト引数が二個取れる亜種が存在する。それ以上の可変長引数版は存在しない。
ちなみに、本当の関数型言語では、関数は単一の引数しか取れない。つまり、二個以上の引数を取る関数は書けない、と言う随分と不便な状況を強要される。
じゃあ、多引数の関数を書けないのか、と言うと、これを理論的に解決する手段が、平たく言うとカリー化だ。ザックリ言っちゃえば高階関数の連鎖だ。
実用上はどう考えてもメンド臭いが、関数型言語は基本的に、小さい基本ルールを設定して、理論的にそのミニマリズムな言語コアをどう拡張していこうか、と言う理論連鎖の塊みたいなトコがあり、実務上で設計されてきた一般のプログラミング言語とは、ちと開発コンセプトが浮世離れしてて、違うトコがある。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

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

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