見出し画像

Retro-gaming and so on

PythonとReduce

龍虎氏の記事を読んでたらAIがとんでもない事を言っている事に気づいた(笑)。


いつreduceの使用が推奨されなくなったんだよ(笑)。
何言ってんだ、こいつ(苦笑)。


どこにもんな事は書いてない
Python2.x時代にはreduceは単なるビルトイン関数だったが、3.0になってからfunctoolsと言うモジュールに移動された。平たく言うと、functoolsと言うのはPythonで関数型プログラミングを行う為のモジュールだ。
しかし移動になった」は非推奨を意味しない
一体何を言ってるの、こいつ?ってカンジである。

Pythonでの階乗計算関数factorial。「非推奨」の場合は、搭載されていても「使うな」とコメントされていて、こういう関数は将来的には消失する可能性がある事を警告している。

もちろん、Pythonは「仕様=実装」言語なんで、いきなり明日reduceが消失する可能性はある。ただ、それは言っちゃえば、Pythonが用意している全関数に関しても同様、なんだ。取り立ててreduceだけの問題じゃなくって、貴方が愛用しているどんな関数だろうと起きうる。
そして、Pythonだけじゃなくって公式な、権威ある仕様書が無いプログラミング言語では同様な「変更」がいつでもあり得るんだ。
それが、言っちゃえばPythonよかRubyの方が安心して使える理由でもある。RubyはISO及びJISで「標準言語仕様」が制定されていて、ぶっちゃけ、作者のMatz氏が「言語仕様を変えたい」と思っても生みの親でさえその根幹設計が弄れないようになっている。
一方、Pythonは何でもアリ、なんだ。言っちゃえば世界で一番Pythonを使ってるGoogleのような企業が(スポンサリングの関係で)、Python.orgに圧力をかければどのような変更でも行う可能性さえある。
そういう事は一応知っておこう。

しっかし、一体どの辺のトンマの発言がこのAIの元データになったんだろう。
どうやら検索してみると、欧米のサイトが元データの模様だ。
なお、通常こういう場合、個人攻撃が好きじゃないんで、リンクを貼らないんだけど、件のブログは個人でやってない事。あと、英語だから一般的には読むのも文句言うのも大変だろ、ってぇんで(笑)リンクを貼る。ここだ。
ちなみに、このページでは別にreduceが非推奨とは一言も書いてない。ただし、AIが書いてるような

sum、all、anyなどの組み込み関数を使って書く方がPythonicであるとされています。

と言う論調なのは間違ってない。
そしてreduceは難読だと言うスタンスではある。
多分こいつらもC言語脳だろう(笑)。毛唐にもC言語脳はいる(笑)。
前にも書いたけど、難読か難読じゃないか、ってのは個人の主観、もっと言うとどう言ったプログラミング経験があるのか、に左右されるだけ、の話だ。reduceに慣れてる層は当然reduceを使ったから、と言って難読とは思わない。逆にC言語みたいに高階関数なんつー機能がない言語で長くプログラムを書いてると難読だと思うだけ、の話だ。
なお、多分検索対象として上位にランクインしてるんで(※1)、多分このブログの主観がAIに影響を与えてるんじゃないかな、と思う。

なお、この記事には色々と面白い事が書かれている。歴史的には全くその通りだ。

Since Python is a multi-paradigm programming language, it provides some tools that support a functional programming style:
  • Functions as first-class objects
  • Recursion capabilities
  • Anonymous functions with lambda
  • Iterators and generators
  • Standard modules like functools and itertools
  • Tools like map(), filter(), reduce(), sum(), len(), any(), all(), min(), max(), and so on
Even though Python isn’t heavily influenced by functional programming languages, back in 1993 there was a clear demand for some of the functional programming features listed above.
In response, several functional tools were added to the language. According to Guido van Rossum, they were contributed by a community member:

Python acquired lambda, reduce(), filter() and map(), courtesy of (I believe) a Lisp hacker who missed them and submitted working patches. (Source)

Over the years, new features such as list comprehensions, generator expressions, and built-in functions like sum(), min(), max(), all(), and any() were viewed as Pythonic replacements for map(), filter(), and reduce(). Guido planned to remove map(), filter(), reduce(), and even lambda from the language in Python 3.

Pythonはマルチパラダイム言語なので、関数型プログラミングをサポートする機能を提供している:
  • 第1級関数
  • 再帰
  • ラムダ式による無名関数
  • イテレータとジェネレータ
  • functoolsとitertoolsと言う標準モジュール
  • map(), filter(), reduce(), sum(), len(), any(), all(), min(), max()のようなツール
Pythonはそれほど関数型言語の影響は受けてはいないが、1993年時点(訳注: Python登場の1991年の二年後)では上に挙げたような関数型言語の機能への明らかな需要があった。
結果として、いくつかの関数型言語の機能がPythonに追加された。開発者のグイドに依ると、当時のコミュニティメンバーによって寄贈されたらしい。

Pythonは関数型言語の機能を恋しく思う(恐らく)Lispハッカーの協力により、パッチを通じてlambda, reduce(), filter() や map()と言った機能を得た。

それから何年も経ち、リスト内包表記やジェネレータ式、sum(), min(), max(), all(), や any() はよりPythonぽいmap(), filter(), や reduce() の置き換えだと見なされている。グイドはPython 3からmap(), filter(), reduce(), そして lambda さえ除く事を計画していた。

いや、確かにPython3が発表される前、ラムダ式が削除候補になってる、って話は聞いた事がある。

PythonはLispの方向へとは成長していない。 Lispに直接影響を受けたPythonの機能はPythonの歴史の非常に初期の段階で追加された。 Guidoは当時、言語設計者として始めたばかりで、 だから「NO」という習慣をまだ身に付けていなかったんだ。 人々が、他の言語からこんなクールな機能を持って来れるよと言ったら、 彼はそのもたらす結果をあまり考えずに取り込んでいた。 最初の数年間、それらの機能は非常に浮いていた。 他のPythonの改善により、最近ではそれらの機能もそれほど浮いてはいないが、 同時に、Pythonの他の新しい機能のおかげで、 それらの機能はあまり重要ではないし使いみちも無くなって来ている。
実際、以下の機能のいくつかまたは全てについて、 それを非推奨にしようという提案が出されている(それほど優先度は高くないが): "apply" (これは現在は第一級の構文となった)、"map"、 "filter" (これはいつもリストの内包表記で置き換えられる)、 "reduce" (forループで置き換えられる)、 そして "lambda" (名前付き関数で置き換えられる)。 これらは明日すぐ取り除かれるというわけではないだろう (悪口メイルを私に送って来ないように)。 だが、これらが削除候補として議論されたという事実がとりもなおさず、 PythonをよりLisp風にしようという動きは無いということを示している。 むしろ、その逆の方向に行くのが好まれているようだ。 (少なくとも、私の意見では "lambda" という名前を持ち込んだのは恐るべき間違いだった)。

ただし、ここで言っておくと、個人的には、

"reduce" (forループで置き換えられる)

なんつーのは馬鹿げた意見だと思っている。逆だreduceforループを置き換える為にある。何度も言うけど、forループを書きたくねぇからreduceを重宝してるんだよ(笑)。
これは何度か指摘してるが、「forループは要らない、何故ならgotoで置き換えられるからだ」と言われれば「バカな意見だな」って思うのと全く同じ理由だ。
抽象度が高いモノを抽象度が低いモノで置き換えられるから要らない、ってのはくだらん理由でしかない。
いや、実際の話、仮にPython3がホンマにこれらの機能を削除してたら、圧倒的に「正統に関数型言語の機能を取り込んだ」JavaScriptやRubyの後塵を拝してただろう。
んで、これから分かるのは、実はPythonはそういう意味だと「確固とした設計計画の下に誕生した言語ではない」と言う事だな(※2)。

ちなみに、このブログの記事の趣旨も全体的には「しょーもな」と思う程度の主張でしかない、って思っている。

リスト内包表記やジェネレータ式、sum(), min(), max(), all(), や any() はよりPythonぽいmap(), filter(), や reduce() の置き換えだと見なされている。

最初に書かれてたこの「結論」を補完する為に以降の記事が書かれているような構造だ。
ちと待てよ、と。
何らかに特化したライブラリ関数があればそれを使うのは当たり前の話であって、別にそれに対してPythonicだ、って主張するようなモンでもない・・・・・・どうもこのPythonicって単語、ロクでもねぇ奴らが使う単語な気がしてる(笑)。
例えばだぜ。数値リストの要素の総和を求めたい、とする。
それはやっぱこう書くべきなんだよ。

>>> sum([1, 2, 3, 4, 5])
15

そうだろ?いくら俺でも

>>> functools.reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])
15

と書け、とは言わん。言ったか?言ってないと思うんだけど。
数値リストの要素の総和を取る関数があるならそれを使うべきだ。当たり前だ。
ただし、reduceは汎化性能がある。sumreduceで書ける。それは指摘したと思う。でもそれが即座に、sumを使わずにreduceを使うべきだ、にはならないだろ。
当たり前だ。

以前、理論的なユーティリティ作成の「流れ」を説明したと思うが。あくまで理論的な話だが。
基本的には「汎化性能が高い」ブツから「特定の用途向け」に徐々にスケールダウンしていくモン、なんだよ。あれ、理論的にそうなる、って話をあんま理解してない人の方が多いの?ちと不安になってきたが。
要は、sum(), min(), max(), all(),  any() ってのは「特定のケースに於いて」reduceを置き換える事が可能だ、ってのはそりゃその通りだ。だってそのためのユーティリティだもん。
じゃあ、sum(), min(), max(), all(), や any() が「どんなケースでも」reduceを置き換えられるか、ってぇとそりゃ不可能だろ?あくまで特定用途であって、汎用性は低いんだ。
ハフマン符号で見せたけど、例えば「葉から根に向かってハフマン木を生成する」お題で、どうやったらreducesum(), min(), max(), all(), や any() で置き換えられるっちゅーねん。無理だろ?
仮にそういう場合に「forループを使えば」とか言われれば、俺ならそんな事を強制する言語はNo thank youだね。んなクソ面倒臭い事書いてられるか、って思う(笑)。
多分この辺なんだよな。そんなにみんなforループとかwhileループが好きなん(笑)?僕のアタマの中では、どう考えてもforループとかwhileループを使う方がメンド臭いんだけど(笑)。考えたくない(笑)。reduce使った方が簡単に書けるじゃん。以上、終了、だ。マジで。
逆に言うと、reduceが分かりづらい、とか言う人間ってマジで「人間の脳みそ持ってんのか?」とか思ってるくらいだ(笑)。どこの世界に「物事をややこしくするだけ」の機能を愛用するバカがいるんだ(笑)。「物事を簡単にする為に」あるに決まってんだろ(笑)。
reduceは物事を簡単にする。従って、reduceを「使うのが難しい」とか「難読だ」って言ってるヤツって単に「フツーの」脳みそ持ってないだけとちゃうんか、とか思ってるんだわ。
パンピーの俺でさえ使えるんだぜ?
良く低レベルのforとかwhile使う気になるよな〜。ホンマそれだけ、だ。そしてそれは「難読」がどーの、って話じゃなくって、単なる「慣れの問題」なんだよ。
それだけ、だ。
そして、プログラミング初学者時代、forとかwhileの使い方練習しただろ?何故にreduceに対しては練習もしねぇで「難読だ」で終わるの(笑)?
不思議な思考回路だ。
練習しとけよ。

いずれにせよ、sum(), min(), max(), all(), any() が使えるケースにはそれを使うべき、でさ。もうこれを挙げてるだけで、恣意的、っつーか「Pythonic」と言うクソコンセプトが想定してる「結論」に誘導しようとしてるのが見え見えなんだよ(笑)。問題はそれ以外の時、なんだ。そういう特定の(ハッキリ言うとビルトイン関数が用意されてない)ケースの時にどうすんだ、って話でさ。
いつか見た通り、Pythonでは80%くらいのケースだとリスト内包表記一本槍でどーにでもなる。残りはほぼreduceで何とかなる、んだよ。それが現実だ
Pythonが最初に登場してから数年の間に、Pythonにパッチを送って協力した(多分?)Lispハッカーの方が正しい、んだ。間違いなく、な。

このさ、何か汎用なモノがまずあって、「特定のケースに於いては」使えるユーティリティとか構文、ってのがある、ってのをまずは押さえないとなんないのね。そこを間違えると件のブログ記事みたいに「何が言いたいんだかよくわからない」発想になるわけ。
・・・・・・んでも、確かに初心者状態だと困る事はあるんだよな。
ちょっと個人的な思い出を話そう。
例えば、ANSI Common Lispの基本的な反復構文にdoってのがある。ポール・グレアムの本だとこんな例が載ってた。

CL-USER> (let ((x 'a))
      (do ((x 1 (1+ x))
        (y x x))
        ((> x 5))
        (format t "(~a ~a) " x y)))
(1 A) (2 1) (3 2) (4 3) (5 4)
NIL

マジに最初見た時「何だこれ?」とか思った(笑)。やたら括弧が多いし(笑)。
でもポール・グレアムに依ると「ANSI Common Lispでは最も基本的で汎用的な反復構文だ」とか書かれてるのね(笑)。
こいつが恐ろしいのは、通常の言語のfor文に於けるカウンターを複数、しかも並列に取れるんだ。上のコード例だとxもyもカウンターになっている。そして副作用も使える、とまぁ「機能的に見ると」超強力なんだわ。
でも見た目酷いだろ(笑)?ここで、グレアムは「通常のユースケースだとリスト相手にはdolist、計数反復にはdotimesを使う」とか書くわけ。
ええええ、doでお腹いっぱいなのに、「専用」まであんの?勘弁してよ、と当時の俺も思ったわ(笑)。

CL-USER> (dolist (x '(a b c d) 'done)
      (format t "~a " x))
A B C D
DONE
CL-USER> (dotimes (x 5 x)
      (format t "~a " x))
0 1 2 3 4

Schemeは割に「再帰一本槍」なんだけど、ANSI Common Lispはホンマ「機能が豊富」で、初心者向け考えるとイディオムが多すぎてどーかな、ってのはあるんだわ。
ただし、だ。dolistdotimesの「存在意義」は今なら分かる。やっぱリスト専用とか、あるいは計数反復用の機構は「あるべき」だ(※3)。
ただし、じゃあこっち2つが「特定のケース専用の繰り返し機構だから」と言ってdoを消そう、ってのは間違ってるでしょ?当然、それ以外のケースも生じて然るべき、って考えるべきで、「いくら括弧が多くて醜くても」絶対doを削除は出来ない、んだ。
これを件のブログのsum(), min(), max(), all(),  any() の例と比較してみればいい。「特定のケースはライブラリ関数で賄える」としても「それ以外」は常に考えとかなきゃならないし、それはPythonicがどーの、と言うクソ意見そのものが間違ってるって事になる。「特定のケースで代替出来るから」汎用性のあるモノを削除、とか考えるのは間違ってるんだ。

さて、もうちょっとツッコんでみよう。
個人的にはPython2.xの時代、「mapfilterが削除候補に挙がってる」って話が出た時、正直言うと「別にエエんちゃう?」とか思ってたんだよな(笑)。何故ならリスト内包表記があったから。明らかにリスト内包表記はmapfilterを更に抽象化した「構文」だ(関数じゃない)。そっちでその辺対応出来るなら、削除してもいいんじゃない?と思ってたんだよ。
しかしながらmapfilterはPython3.xでも生き残った。全く別の機能を持って、だ。
Python3.xではmapfilterもクラスになっている。

>>> map
<class 'map'>
>>> filter
<class 'filter'>

つまりこいつらは関数じゃない。もっと言うとイテラブルを返すイテレータだ。
このイテレータ、ってのが実はややこしいんだよな・・・・・・。いや、僕は概念を知ってるし、他のモダンな言語のユーザーなら当然把握してるだろう。
ところが、この存在ってどう考えても初心者には分かりづらい存在なんだよな。イテレータってそもそも何?と。
いや、その辺の話ってこのブログでもいっぱい書いてるよ。でも初めてPythonに触れる層にはワケワカメなのは間違いないと思う。大体、こいつらを変数に代入してイテレータとして使った時点で「消えてしまう」と言う話を書いたが。そんな挙動を一体ニューカマーの誰が想像するだろうか(※4)。
イテレータはPythonへのニューカマーに対しては鬼門だ。しかしながらPython3.xでは既にあっちこっちでイテレータだらけ、になっている。そしてPythonユーザーはニューカマーに対して「実行効率で・・・」と説明せなアカン状態になってるが、何度も言うが、そもそも実装上で云々、ってのは理由にはならないんだ。ある言語で実装上で云々、って言い出した時点で、個人的にぶっちゃけると、その言語から離れる時期に来てる、と思う。Pythonはまだ比較的マシだ、ってだけの話だ。
ハッキリ言うと、既にPythonはプログラミング初心者に対して優しい言語ではなくなっている。イテレータの概念が分からないと使えない、ってのは既に初心者に、ある程度高度な概念を理解しろ、って強制してるに等しい。
皆言うだろ?先人は。Pythonは優しく覚えやすく、初心者向け、だと。ハッキリ言うと、それは現在のPython3.xを見て言ってるんじゃなくって、彼らが過去の時点で学んだ時のPythonのイメージで言ってるんだ。Python1.xの時学んだ人はPython1.xのイメージで。Python2.xの時学んだ人はPython2.xのイメージで。誰も決して現在のPythonに付いては語ってない。
これなんつーのかね、名前付けたい法則なんだけど、敢えて言うと長年関わってるおっさんの方が有利な法則?例えば僕みたいにPython2.x時代にPythonを学んだ人は、3.xを「差分」として捉えるんだよ。過去のPython2.xで「学んだ事」に対して3.xは「追加で変化があった」って捉えるのね。差分を学ぶ事自体は大して苦にならない。
一方、ニューカマーが3.xにいきなり触れると「一貫してねぇじゃん!」って捉える確率が高い。過去に学んで「一貫してて」、現在そこに「ズレ」が生じていても、過去に学んだ人はその「ズレ」に気づかないんだわ。
これ、Pythonだけ、じゃなくってコンピュータ関係では良く起こると思う。OSとかさ、色んなレベルで。古い時代からのたくってた人の方が「差分を学ぶ」分にはラク、なんだけど、「イチから全部覚えないとならない」ニューカマーにとっては、そのブツが「一貫してる」とはとても思えないんだ。
特に、この、Pythonのようなイテレータ増殖状態になってると、ついつい「実装上こう有利なんで・・・」とか言い出す事になるわけだが、それって「一貫してて初心者向け」ではなくなってるって言う危険な兆候なんだよな。オリジナルのPythonの目的には明らかに反してるだろ?
Pythonは結構そういう危険な水準に達してて、オリジナルの開発者であるグイドが「Python 3000では・・・」とか言い出した時点で実はかなり怪しかった、って捉えた方が本当はいいと思ってる。繰り返すけどPythonは既に初心者にも分かりやすく優しい言語ではなくなっている、と言う事だ。
かと言って、実装側から見ると遅延評価モドキを持たせる、って事は魅惑的だし、実際パワフルなのは間違いないんだよな(※5)。仮に関数型言語的機能と合わせてそれらを削除するとしてみよう。そうなったら最後、Pythonはマトモなスコープを持たないVBよりも酷い言語と化すと思う。言い換えるともはや引き返せないんだよ(笑)。行くトコまで行かんとダメなんだけど、グイドは既にいない。
割にグイドは良いタイミングで「Pythonを造り続けるのを止めた」とは思う(笑)。次に造る言語は(造るとすれば)もっとマシな言語になるだろう(笑)。
そして、全員がPythonに折伏されたわけでもなし、そろそろタイミング的にはまた新しく「初心者に優しく一貫した言語」が出てくるんじゃないか、って思う。
それが出たら完璧だって?いや、そいつも10年、20年かけてダメになっていくだろう(笑)。
そういうモン、なんだって。
歴史は繰り返すんだ。

いずれにせよ、安心してreduceを使ってくれ。何度も繰り返すけど、Pythonでは最重要関数だ。マジで非推奨になるまでそう思っていていい。
仮に非推奨になったら?安心しろ、その時にはハッカー達はPythonから去っている(笑)。
いや、去らないかもしんないけど、その時はPythonはライブラリを使う為の言語になっていて(今もその気があるが)プログラムを書く為の言語ではなくなっているだろう。ユーザーはレゴブロックのように、既存のライブラリ関数を貼っつけるだけになる。
つまり、ハッカーもライブラリを使うだけ、となり、Pythonを使って自分でプログラムを書こうとはしなくなるだろう。
残るのはPythonハッカーじゃない、単にPythonicな奴らだ。彼らはC言語脳の亜種だ。そしてハッカーが去ったPythonはPython自体に魅力があるわけじゃなく、C言語のように仕事で使う為の、就職の為のプログラミング言語となっているだろう。
繰り返すけど、就職の為のプログラミング言語、なんざハッカーは気にしない。
Pythonがそうなるかどうかは知らん。
知らんけど、今のトコは、安心してreduceを使い続けて極めるべきだ。
そしてreduceを学べないようなら、Pythonの価値なんざ無いんだ。
是非ともメジャー言語でreduceを使いこなせるチャンスを失わないようにしよう。Pythonicな奴らに騙されるな(※6)。

※1: ちなみに、現在だとパーソナル検索が基本なので、Googleでは「検索順位」が分からない、って考えた方がいい。Googleは貴方の行動をトラッキングし、「貴方の検索傾向」あるいは「貴方の過去の検索履歴」に準じて検索結果順位を反映して返す。
従って、「貴方が得た検索順位」が誰から見ても「同一だ」と言う保証がない。
2024年現在、本当の「検索順位」を知りたい場合は、DuckDuckGoなんかの「個人情報をトラッキングしない」検索サイトじゃないと分からない、って言って良い。Yahoo!なんかも検索エンジンは既にGoogleを採用してるんで、このテのメジャーポータルサイトでは「検索順位」は分からん、って言って良いと思う。
結果、SEOなんかで「うちのサービスを使えばGoogle検索の順位が上がりますよ!」なんて言って営業をかけてくる会社は詐欺なんで気をつけよう(笑)。自分がしょっちゅう自分のサイトのGoogleでの表示順位を気にして検索する以上、自分が一番自分のサイトを検索してるわけで、「貴方のパソコンでは」検索上位にランクインして当然なんだ(笑)。
(逆に「DuckDuckGo」での検索順位を上げる、なんて営業をかけてくる会社があったら、貴方が「DuckDuckGo?ナニソレ?」と思っても、相手は凄腕だ、って事になる)
ちなみに、個人的には不思議なんだけど、こういう「Google検索の特性」ってのは当然だと思ってたんだけど、知らん人が意外と多いらしい。件のC言語脳のサイトではないが、「かつて女子校でプログラミングを教えていて、定年で引退した教師」が作った、とか言うC言語教育サイトがあって、「私のサイトはGoogle検索一位です。だから信用に価します!」的に大々的にトップページに書いてたが、Googleパーソナル検索が基本のこの世の中でそれを「知らん」ヤツが言ってる事の一体何が信用出来るんだ、とか呆れた経験がある。
それはあんたのPC上「だけ」の話なんだよ、と。

※2: オリジナルのブログではPythonのオリジナル開発者、グイドの記事へのリンクや「関数型言語機能をPython3.x(当初はPython 3000と仮称してた)から取り除きます」と言った決意表明の文書へのリンクが貼ってある。
これがなかなか面白く、グイド自身は「reduceが嫌いだ。分かりづらいから。」って思ってた事が伺える(笑)。
ただ、ポール・プレスコッドも書いてるし、グイド自身も書いてるけど「lambdaと言う名前が失敗だった」ってのは多分その通りだと思う。実際、lambdaと言う「何を指してるんだかサッパリ分からん名称」は「関数型言語を知ってる人しか分からない」って意味では、間違いなくサイテーの名称決定だろう。内輪受けに等しい
グイドが書いてた事を要約すると「ラムダって名称はねーんじゃねーの、って思ったんだけど、"マトモな名前の代案"が無かったからしょーがなかったんだよねー」との事(笑)。
現に、JavaScriptを始めとしたモダンでマトモな言語では、「概念的な」ラムダ式は、もはやlambdaと言う長ったらしく意味のないキーワードを採用しない流れになっている。
なお、個人的な意見を言うと、ラムダ式は「グイドも書いてるように」へなちょこだし、無くても構わない、って言えば構わない・・・大域関数なりローカル関数を書いてそれを使えば実用上は充分、だからだ。
ちなみに、グイドのブログの後半に書かれてる例とかはあまり説得力がある例とも思えず、「それはPythonにマトモなスコープがないからだろ?」としか思えん(笑)。そしてそれはいまだに直ってない、のだ。

※3: これも何度か言ってるけど、個人的には、Racket用個人的ユーティリティとしてはdolistdotimesを備えておくべきだと思っている。マクロを書く良い練習になるし、それこそ、特定のケース(つまり簡単なリスト操作や計数反復)なら、ヘタに再帰を書くより遥かに短くコードを仕上げる事が出来る。
この2つはRacketを使う際に常に用意しておくべきだ。

※4: 何度か書いてるが、個人的にはこの現象を避ける為には無引数ラムダ式で包んで「サンク」にしてしまうのが一番良い、と思っている。
ただし、予想は付くだろうが、そもそも「サンクと言う概念」をプログラミング初心者に説明する事自体が厄介だ(笑)。
人によっては、単に組み込み関数listを使ってリストにしちゃえばエエんちゃうの?と言うだろう。それはある意味正しく、ある意味間違っている。
と言うのも、第一に、リスト化した時点で本来イテラブルが持ってる「利点」が消失する・・・そもそもイテラブルは「計算の約束事」を抽象化したモノで、メモリ効率が良い筈、なんだ。リストとして実体化した時点でそれら「効率性」が消えてしまう。
第二に、イテラブルが「必ず終了する」と言う保証がない。イテラブルは「無限長データ」を扱う可能性がある。つまり、リスト化しようとした時点で無限ループに陥るんだ。
その辺を鑑みると、圧倒的に無引数ラムダ式で包んでサンクにした方が良い。・・・・・・しかしそれは「コンピュータサイエンス的な」判断であり、とてもじゃないけど「プログラミング初心者向け」のトピックにはならないんだ。
結果、本文で書いてる通り、既に「Pythonは初心者に優しい言語」ではなくなっている。

※5: 例えば、以前見せたイテレータ、余再帰を使うと無限長の素数列を返すイテレータなんかを簡単に書けてしまう
itertools.takewhile等を使えば、



等と、無限長の素数列から好きなだけの長さの素数列リストを生成するマジックを使える。
もっともこれはマジックでも何でもなく、キチンとした理由があり、非常に強力で、結果「愛用すべき機能」なのは間違いないが、同時に、「プログラミングへのニューカマー」にとってはやっぱり説明は厄介だ。
結果、Pythonの「何でもかんでもイテレータ/ジェネレータ化」と言う方針は、既存ユーザーにとっては「便利」だが、一方、新人を切り捨てるような方針になっている、と言う事だ。

※6: Pythonic ≒ C言語脳、ってのは語尾にCが付いてて喜んでるんじゃねーの、って疑いから来てる(笑)。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

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

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