見出し画像

Retro-gaming and so on

ちと感動してた話

以前、「関数型言語脳テスト」と言う話を書いた。

実際のトコ、プログラミングで、「関数型言語のような流れ」で発想する人は少ないとは思う。
多くのプログラミングに関わる人はいまだにBASIC的な発想でプログラミングしてるんだ。
その古典的なBASIC的発想でのプログラミング方法をモダニズムでラッピングしてるように見せるのが「オブジェクト指向」の殆どのケースだ。
言い換えると殆どの人は「クラス内BASIC」を書いてて、そのクラス内では大域変数的なプログラミングを施している。
良いか悪いか、の話はしてない。
どうやら「そういう発想の方がフツー」ならしいんだよな。

その辺がプログラミング教育の「やり方」で変わっていくのかどうかは知らん。変わっていくんだとしたら、取り敢えず、教育界に蔓延る悪質な「C言語脳教師」を排していくべきだと思う。
そうじゃなくって、人の「タイプ」によって「BASIC的なプログラミングをする人」と「関数型言語なプログラミングをする人」に本質的に分かれてるんだとしたら、人のタイプを見て教育方針を変えなアカン、っつー事だ。
そしてそうだとすると、「関数型言語な考え方をする層」、つまり関数型ネイティヴってのはかなり割合が低くなるのではないか。

そう、関数型言語な考え方をする人ってのは少ない。
教えて!gooの回答者でもまず見かける事がないんだ。

ところで、教えて!gooのJavaScriptカテゴリにこういう質問が上がってた。

0000 〜 9999 までの 10000 通りの配列から、
この各数列の中で、任意の数字を 1 つ決め、1 つ以上の同じ数字がある場合、
例えば 6 とします。その場合、6679 や 6669 、 6666 などなどを削除したい場合。
どのようなロジックを書けば良いですか ?

そもそも 10000 通りの配列って簡単に生成することはできますか ?

わかる方、教えてください !

まぁ、この問題はちと曖昧なのは事実だ。実際のトコこの場合の「配列」がどんなデータになるか、ってのがイマイチ不明である(0、じゃなくて0000、ってのが一体何を表すのか議論の余地がある、ってこった)。
それはともかくとして、回答者側で凄まじい回答を投下してる人がいた。
こんな解である。

const n = 100;
let ary = [...new Array(n)].map((e, i)=> ('000' + i).slice(-4)).filter( e => e.indexOf ('6')<0 );
console.log( ary ); 

人によっては「悪趣味なワンライナーな記述」って言うかもしんないけど、ハッキリ言って違う。
この人、fujillinさん、って人は関数型言語な人だ。JavaScriptを使いこなしてる。
いや、違うな、「JavaScriptの元々の設計方針/意図に従って」プログラムを書いてる人だ。だから上のコードは「悪趣味なワンライナー」なんかじゃなく、「元々JavaScriptはこういう書き方を想定してるんだ」と言うような書き方なんだ。
思わずそのコードを見た時、ニヤッとしてしまった(笑)。そう、Lispだと当たり前の解なんだよなぁ。そして何度か言ってるけど、JavaScriptは「Cの皮を被ったLisp」だ。
なかなか関数型言語な人は見かけないんで、つい嬉しくなっちまった、と言う話だ。

それより重要なのは、手元のスタンドアロンJavaScript処理系であるRhinoだとfujillin氏が書いたコードが全く動かない辺りだ。これにも感動してた。


いや、皮肉を言ってるわけじゃない。実際問題、殆ど1年毎に仕様がアップデートしているJavaScript(と言うか正式にはEcmaScript)にRhinoはキャッチアップしてねぇんだよ。言い換えるとRhinoで扱ってるJavaScriptは「古いそれだ」と言う事になる。
っつー事は、だぜ?要するに、fujillin氏はキチンとEcmaScriptの仕様に目を通してアップデートしてる、って事だ。
こんな人はなかなかいない。
世の中「得意言語はC言語です」とか言いながらANSI Cスタイルで書いて、C11とかC17知らない人ばっか、なんだぜ?
ANSI Cは既に公的にはC言語じゃねーんだよ。
そして得意げに

「コメントに//は使うべきじゃないよ。本当は/* */で書くべきだ。」

とか言う人が山ほどいる、ってのが実情だ。お前それ一体いつの仕様の話してんだ
分かる?これくらい「勉強したくない」人の方がむしろ多いんだわ。
反面、fujillin氏はEcmaScriptの仕様にキチンと目を通してる、って事なんだろう。Rhinoで動かないコードを書く辺り、勉強しまくってる、って事なんだ。
素晴らしい。珍しく感動してた。
(また、教えて!gooだと「コードを書かない」回答者の方が多いんで、「感動する」機会があんまない)

ちなみに、fujillin氏が書いたJavaScriptのコードとほぼ同質なコードをRacket/Scheme(※1)で書くと次のようになるだろう(SRFI-13を使用する)。

(filter (lambda (x)
   (not (string-any #\6 x)))
  (map (lambda (x)
     (string-pad
      (string-append "0000" (number->string x))
      4))
    (range 10000)))

Pythonなら次のようになるだろう。

[x for x in [f'{i:04}' for i in range(10000)] if '6' not in x]

結果、この質問も「関数型言語ならどう考えるのか?」をテストするには割に良い問題だと思われる。

※1: SchemeにはPythonのようなrangeは用意されてないので、SRFI-1iotaを使えばいいだろう。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最近の「プログラミング」カテゴリーもっと見る

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