id:cametan_42
東大ではPythonは”教養”レベルの様子で、教養学部のテキストが販売されています。
ああ、上の方にも書いたけど、これでしょ?もう一方のこれと共に、「あー、今、プログラミング入門やるんなら統計は外せないなぁ」って思ったきっかけになった本です。あー、回帰分析やるかぁ、とかね(笑)。こっちは最小二乗法じゃなくって最尤法にしたる、とか色々余計な野望を抱えるようになってしまった(笑)。
実はより正確に言うと、東大の本はMITの本のパクリ・・・と言うか、エッセンスを纏めてコンパクトにしたニュアンスかな・・・。MITの本は分厚くて、版を重ねる度に高額化してんだけど、一方、東大の本はMITの本からトピックを取捨選択して1学期で扱える容量へ、と整理してるカンジ。本当にそうなのかは分からんけど、少なくともコンセプトは物凄く似通ってますね。
この2つの本共々、割に良書で、「プログラミングを学ぶなら現代生活では、常識としてこの辺りは押さえておかなければならない」的なコンセプトで纏められていると思います。言い換えると純粋なプログラミング本ではないし、また実はPython本でもない。本当「プログラミングを通じた、現代に横たわる問題解決の手段」提供のほんの触り、ってカンジかしらん。確かに「教養学部」的なんですよ。
ただ、プログラミングスタイルは気に食わなくてね(笑)。僕の場合は、JavaScriptに近い抽象度の高さの他のプログラミング言語に対しては水平的に移動可能、って事を考えてて、結果、JavaScriptのコアが持つモダンな機能を使う事とか解説する事を畏れないし躊躇しない。と言うかガンガン書く。
一方、東大本/MIT本の場合、本当に全プログラミング言語が共有してる構文を逸脱しないように書いてるのね。これが気に食わなくてさ(笑)。
必然的に、C/Pascalでも書けるような機能限定で使う、って話になっちゃって、Pythonのファンシーな機能は全く使わない、って事になっちゃう。
下の方にも書いたけど、最初のスタイル提示って大事で、最初に、言っちゃえば古臭い?古典的なスタイルのコーディングスタイルに慣れたらそこから脱却するのは恐ろしく難しい。
「女ははじめての男を忘れない」は都市伝説だけど、「プログラマははじめてのプログラミング言語/コーディングスタイルを忘れない」は厳然とした事実だと思う。
だからコンセプトは分かるんだけど、そういう意味だとこの二冊は諸手を挙げて「良書だ!」とは言えなくなっちゃうんですよね。ただまぁ東大だとね。工学部行って専門的にやるとなったら。後ろに控えてる老教授とかさ(笑)。「うひひひひ、Haskellは楽しいのう、ふぉっふぉっふぉ」とかのたまう黒幕的な爺さんとか山ほどいるし(笑)。そういう層がぶ厚いのが東大の強みだろうし。ヘンな研究室入ったらすぐ洗脳されるだろうし(笑)。
そういう意味では全然心配しない(?)環境なんですけれども。
まぁ、東大にとってはPythonなんて、ショッカーの戦闘員程度でしかない(笑)。後ろに控えてる人達は怖いぞ〜(笑)。なお、MIT本を書いたJohn V. Guttagって人は、生粋のMITっ子じゃなくって、外部から来た人で。つまり、伝統的なMITハッカーの系列にいない人なんです。
学派ってあるのかどうか知らないけど、基本的にこの人は・・・知ってるかどうか分からないけど、「オブジェクト指向をやるならいつかは学べ」って言われるEiffelってプログラミング言語を作ったバートランド・メイヤーに近い立ち位置なんです。いわゆる契約プログラミングの人で。
だから「ハッキング」じゃなくって「ガッチリしたコードを書く」派なんで、そんなトコで、彼の書いた本のPythonのコードは遊びが少なく、ガッチリとした古典的なコードになっておりまする。
その辺も東大と相性良かったのかしらん。○○スクールも、そこに通う生徒も、何か使えている雰囲気=インスタントな成果、のような勘違いがタイパ+コスパ志向と相まって、それで納得、充足してしまっているのではないかと思うんですよね。
うん。あるでしょうね。
と言うか「転職したい!組」とかさ。なんかそれこそスクール系宣伝に乗せられてんのかな、とか。
JavaScriptなんて「良く使われる」でしょ?「フリーランスエンジニアになるのは簡単!」みたいな嘘っぽい話の推奨言語っぽい扱いで(笑)。で、釣られた人は、大体途中で分かんなくなって自滅して消えるのね(笑)。
いやホント、最低でも大学が「胡散臭く」ならなきゃいいのにな、とか思うんだけど、これがまたねぇ・・・。これは他所で話していた、REPLとMVCループでGUIアプリ…的な話題へのanswerだろうか。
はははは(笑)。
いや、まぁそういった意図ではないです。
まぁ、あそこの質問者がどーの、って話ではなく、独学しようと大学で学ぼうと、実はREPLを知らない/REPLを何のために学んだのか分からない、ってのが一般的になってる、ってのが事実です。
実は僕は独学組なんだけど、驚いた事に、各Q&Aサイトに投稿された学生の質問とか見る限り、最悪な事に「教授する側」が何のためにインタプリタ実装を教えるのか分かっていない、と言う驚愕の事実が透けて見える・・・・・・。
別に元々、「アカデミックだから」その議題があるわけじゃないのにね。汎用的なソフトウェア開発方式で、もっとも汎用的なプログラムだから「インタプリタを選んでる」んだ、って事実を恐らく教える側が分かっていない・・・・・・。
んで、どうしても技術的に派手なんで、このトピックの時、枝葉末節の「字句解析」とか「構文解析」に話がすり替わって「木を見て森を見ず」になるらしい。
まぁ、その辺、このテの話を扱う大学ならまだマシな方で、今だとかなりの確率で「Pythonならライブラリを使えばこんなに簡単にプログラムになりますよ〜」ってやってるらしい(笑)。プログラミングのやり方教えないでPythonの外部ライブラリの使い方ばっかやってるみたいなのね。Javaスクールの危険、どころか、今じゃPythonスクールの危険、だ。
Q&Aサイトで良く見かける「Pandasで・・・」って質問は鬼門だ。典型的には彼らは「プログラミングの仕方を知らない」。Pythonにおけるデータ型の振る舞いを知らない。それどころか「Python本体とPandasは全く関係がない」と言う事実を知らない。
誤解のないように言っておくけど、質問するな、って言ってるわけじゃないです。質問する事自体は良い事だ。問題は、彼らは「質問先」さえ知らないんだ。特定のライブラリが人気がある場合、提供先は初心者用フォーラムを設置してたり、ユーザーズグループがあったり、はたまた懐かしのメーリングリストを持ってたりするだろう。ところが、そういう情報を全く知らない。つまり文字通り「何も教わっていない」んですよ。
ハッキリ言うと、学生側が悪いんじゃない。むしろ教授側の問題で。「出来る出来る出来る」と連呼するだけで「出来なかった時どうするのか」全く指導していない。
そしてそういう欠点をGoogle Colab採用がまた加速させる(笑)。
これが知る限り、現在のPythonスクールです。かつては(具体的には2015年以前)、「Pythonを知ってる」ってのは「プログラミングが出来る人」と同義語でした。何故ならまだまだPythonはマイナーだったし、そんなマイナーな言語をわざわざ学ぶ、ってのはその人にプログラミング愛があって、学習意欲が衰えていない、って意味でした。
今や「Python経験者」と言うのは「プログラミングがまともに出来ない人」って、意味が180度変わっちゃった。はたまた、whileを再帰化させるお題?
whileブロックを、関数loopWorld(environment)に置き換える。
とはいえ、いつぞやのブログでは末尾再帰最適化が実装されていないとか、あえてのwhile実装なのでしょうが。本当は、末尾再帰で書ければ完全な「関数型プログラミング」なんですけどね。ただ、トランポリン関数をこの時点で全くやってないんで(第1章のすぐ後に挿入予定)、苦肉の策(笑)でやっぱwhileと再代入を使わざるを得ない、と(笑)。
いずれにせよ、こういうのはいかんですね。
中途半端にコードが読めるものだから、ふと目にしたコードが中途半端に短ければ、そのまま読み終えて、中途半端に時間を浪費してしまう。
隙間時間にゲームを始めて、隙間時間消費どころではなくなった、みたいな。
これは、いけません。いや、本当にすみません(苦笑)。
邪魔しちゃったなぁ。原稿はLinuxで書いてるんだけど、確認の為にソースコードをWindowsに持っていくのがめんどくさくってさ(笑)。
あれ、Hatena PARKSにコード貼っつけてWindows側からそれをコピペすりゃ良くね?とか思ったら案の定そうだった(笑)。
なんか、Google Driveも重いしメンドイんだよね〜。また、最近仕様を変えたのか、Linux側にセッティングしたクライアントが死んでいる。おい、Google、ホントお前らマジメに仕事しろよ(怒さて、今は今まで手つかずで放っておいたCase Study 1の原稿を書いている。Cae Study2 と3は既に終了してんだけど、Case Study 1はちょっと難しくてね。
要は読者にまずは「写経」をさせようとしてる。ネタは「数当てゲーム」だ。上のソースコードは完動品の2歩くらい手前のブツだ。
多分知ってる人は知ってるだろうけど、元ネタはこれだ。別にRustに偏重してるわけじゃないんだけど、ネタ選びとして「プログラミング入門」的な書籍で、二冊くらいで「ネタが被ってる」ブツは、教育用として良いネタなんじゃないのかな、ってぇんで取り上げている。同じネタを選んでいるのは、アプローチは違うんだけど、Land of Lispなんかがそうだ。
要はこのテの「ネタ」にオリジナリティとか要らんのよね。フォーカスすべきは「教育効果が高いのか低いのか」だ。
同様な理由で、入出力を学んだ後に「99 bottles of beer」なんかも扱おうかな、って考えている。もちろん既にプログラミングを学んだ層にはハナクソなネタなんだけど、それでも初学者は意外と躓く。ちなみに、「最初のプログラム」で
console.log("Hello, world!");なんかやらない(笑)。こんなもん書いても意味がない(笑)。
しかもこれ、「JavaScriptのプログラム」でさえない(笑)。正確には「WHATWGが定義したWeb APIを使ったプログラム」であって全くJavaScriptと関係ないんだ。つまり二重の意味でダメなサンプルだと言える(笑)。
「なんとなくみんなHello Worldから始めてるから」ってのはダメなんだよ。もうそろそろ最初のプログラム = Hello Worldから脱却すべきだ。1970年代じゃねぇんだから。教育効果で「最初のプログラム」を選ばなきゃいけない。さて、Rustのこれは構成としてはなかなか見事なんだよ。だから方針としてこれに沿う事にした。
ただし、敢えてケチをつけると、実はそれ、結果として「Rustでの望ましい書き方のプログラム」にはなってないんだよね。変数の破壊的変更(mutation)もやってるし。ましてや「一般論としても」良いプログラムだとは言えないだろう。
もちろん、「簡単なサンプル」を例として、Rustのいろんな機能やその「考え方」を紹介するには良く出来てるんだ。むしろそれをやりたいが為に「こうしている」と言った方がいいだろう。分かる。
なお、別にRustだけじゃなくって、Land of Lispのアプローチなんかでもそうだ。「駆け足で、プログラミングってのはこう行うんだ」ってのを紹介したい、ってのが目的で、別に「キレイなプログラムの書き方」を論じたい、等と言った意図はない。
でも本文書では最初から「キレイなプログラムの書き方」、つまり「設計技法」にいきなり突っ込んでいる。キーワードはRead-Eval-Print Loopだ。プログラムはRead-Eval-Print Loopが成立するように書け、と最初から言う。これ、随分と敷居が高い、って思うかもしんないけど、個人的な観察だと「最初から方法論を提示した方が良い」って思ってんだ。
と言うのもだね。今じゃ少ないだろうけど、例えば大学に行っていきなりC言語学ばされるじゃない?そこで最初に習う「やり方」ってさ。「main関数に何でもかんでも書いてprintfまみれにする」プログラムなんだよな(笑)。だろ(笑)?
のちに関数定義を・・・かなり後で習うんだけど、「なんで分割せなアカンの?」ってアタマの中に「?」マークが飛んでたヤツも多かった筈だ(笑)。「え、何で今さら?mainに何でも突っ込んでたらエエんとちゃうん?」と(笑)。
「いや、俺は違ったぞ。最初から対応出来てた」って人もいるだろ。ハッキリ言おう、それはあなたが優秀だったからだ。そしてあなた以外のかなりの数は、大体そういう「方針変更」の意味が分からなくって、その考え方に馴染めなくって、ドロップアウトして消えてくんだ(笑)。だからあなたは「そういう人が多かった」と言う事実に気づかない。
これはかなり重要な事を示唆してる。つまり、スタイルを最初に提示するのは極めて重要だって事なんだよ。加えると途中でのスタイル変更に人は馴染めないんだ。
人間は「枠組みを頼りにして考える」。枠組みを拡張したり、あるいは何かを付け加える場合には抵抗を覚えない。一方、「枠組み自体を取り替える」事に抵抗を感じるものなんだ。C言語教育で見られるように「なんでもmain関数に突っ込んでベタ書きする」ってのを「機能を小分けして関数にする」に変えると言うのは「枠組み自体を取り替える」に等しい。いきなり登場したパラダイムシフトと言って良い。
だからここで躓く人が多いんだ。
だからこそ、この文書では、いわゆる「プログラミング入門」に良く見られる、ベタ書きのスクリプト的プログラムは一切書かないし教えない。また、最初の「写経用プログラム」さえ、Read-Eval-Print Loopと言う設計構造を提示する道を選んだ。これが本文書を通じての「基本技法」と言うか、「基本スタイル」になるからだ。
要は、計算と入出力を混ぜるな
と言うメッセージを最初から提示している。つまり「副作用は分離しろ」だな。
またこれも特徴的だろうが、「メッセージの外部化」も最初から提示してる。メッセージテーブルを作成して、出力にMagic Stringをハードコーディングする、ってやり方は厳禁、としてる。とまぁ、今はそんな事を書いている。
もうすぐ終わる筈だ。終わりたい。終わるかも。ちょっとごめんよ、通りますよ、っと。
const $MessageTable = new Map(); $MessageTable.set("guess", "Guess the number!"); // 数を当ててごらん $MessageTable.set("prompt", "Please input your guess\n "); // ほら、予想を入力してね $MessageTable.set("youGuessed", (guess) => `You guessed ${guess}`); // 次のように予想しました: ${guess} $MessageTable.set("failure", "Failed to read"); // 読み込みに失敗しました $MessageTable.set("Less", "Too small!"); //小さすぎ! $MessageTable.set("Greater", "Too big!"); //大きすぎ! $MessageTable.set("Equal", "You win!"); //やったね! class World { constructor(secretNumber, guess, ordering) { this.secretNumber = secretNumber; this.guess = guess; this.ordering = ordering; } } function initializeWorld() { return new World(Math.floor(Math.random() * 100 + 1), null, null); } function read( message = $MessageTable.get("prompt"), errorMessage = $MessageTable.get("failure"), ) { const guess = Number(prompt(message)); if (Number.isNaN(guess)) { throw new TypeError(errorMessage); } else if (guess > 0 && guess < 101) { return guess; } else { throw new RangeError(errorMessage); } } function worldGo(x, environment) { return new World( environment.secretNumber, x, x < environment.secretNumber ? "Less" : x > environment.secretNumber ? "Greater" : "Equal", ); } function print(environment) { console.log($MessageTable.get("youGuessed")(environment.guess)); console.log($MessageTable.get(environment.ordering)); return environment; } if (import.meta.main) { console.log($MessageTable.get("guess")); let environment = initializeWorld(); console.log(`The secret number is: ${environment.secretNumber}`); //秘密の数字は次の通り: ${environment.secretNumber} while (true) { environment = print(worldGo(read(), environment)); } }GoogleにとってのChromium、Chrome、ChromeOSは、Microsoftにとっての.Netに相当すると思うのです。プラットフォーム問わず、.Net上でC#、F#、さらにPowerShellを動作させる如く、どこでもJavaScriptフロントエンドを動作させる。
いい着眼点ですよね。マイクロソフトは共通言語基盤、GoogleはWebブラウザ、だと。
どっちも仮想的な意味ではプラットフォームですもんね。closure-compilerは2009年11月だということで、Ajaxが盛り上がっていたころだと思います。
うん。昔聞いた事あるような気がします。
と言うのも当時はJavaScriptの方は全然知らんかったんだけど、ClojureとかClozureが出てきた時とほぼ同時期なんですよ。「みんなクロージャすっきやな〜」みたいな(笑)。「Google、お前もか!」みたいな(笑)。
そういう「名前の連鎖」があったんで、良く覚えています。
Googleが作ったのは何か、ってのは良く知らんかったんですけれども。なんか、GoogleってJSの最適化に血眼になってる、って印象ですよね(笑)。
そもそもGoogle V8自体が「これでもか!」って程の最適化の極みのような処理系ですしおすし。
まさか、マイクロソフトが(あくまでJS処理系として)Googleの軍門に降る、とか昔なら思いもよらなかった性能なんだよなぁ・・・・・・。ここのスレ主であるid:espio999氏がJavaScriptスタンドアロン処理系、Denoについてのちょっとしたノウハウ記事を書いている。
僕が紹介するのもおかしいんだけど(笑)、一応貼っておこう。
npmと言うのは、Racketで言うraco、Rubyで言うgem、Pythonで言うpip、にあたる、Node.js用のパッケージ管理システムだ。そしてその背後には膨大なソフトウェアアーカイブがある。
もちろん、サーバーサイドJavaScriptと日常的に格闘している人達にはおなじみだが、一方、JavaScript初学者/初心者〜アマチュアJavaScripterには意外とそうでもないだろう。
元々、DenoはNode.js開発者であるライアン・ダールが「てへッ😜Node.jsは色々と失敗しちゃったよ🙇♂️」と反省して作ったシステムだ(だからNodeとDeno、と一種アナグラムになっている)。
しかし、膨大なNode.jsで得られたライブラリ・アーカイブは捨てる事なく、「タダ乗りする」と言う大変正しい戦略をDenoに持たせている。これにより、Denoは「無一文でスタートせざるを得ない」と言う状況を避ける事が出来た。Google Closure Compilerは最適化ツールの話。これも最適化具合を上げすぎると不具合が出る、なんつーのも、gccの最適化等を知ってる人にはお馴染みだろう。
「過ぎたるは猶及ばざるが如し」の意味を我々に思い出させてくれる機能だ(違結構ね。だから初代が「突貫工事で作られた」割には良く出来てる、ってば良く出来てる(笑)。
ただ、「プログラムのバグの混入率の高さ」とかさ。結局その辺で泣かされる人も多くて。
結果、マイクロソフトが「こりゃあかんがな」ってぇんでアンダース・ヘルスバーグ(元Borlandの人で、TurboPasal/Delphiを開発した言語実装界の重鎮/C#の設計者)を中心として作らせたのがTypeScript、となっておりまする。
アンダース・ヘルスバーグなんて、「厳格な型が特徴の」Pascalの実装者だったわけですから。もう型に対して一家言あります、なんてもんじゃない(笑)。動的型付けだったJavaScriptにアノテーションベタベタ貼りまくって(笑)、言っちゃえば「エラーを起こしにくい」JavaScriptに改造したわけだ。元々、JavaScriptプログラムのバグの最大の原因が「型に関してのあまりにもルーズな反応」だったわけだからね(笑)。考えてみたら存在しないのとゼロなのを区別できないとデバッグの時に困りそうですかね・・とりあえず動いてしまうんで。
これがね。そう、JavaScriptのある意味「思想」なの。
「間違ったコードを書いても取り敢えず動きはする」って設計になってんのね(笑)。ここが他の、言っちゃえば「マトモな」プログラミング言語との最大の違いだ。
フツーのプログラミング言語の場合、言わば「端末上で動く」前提なんで、書いたプログラムが間違っていた時、結果「止める」のが有効なわけだ。
ところが、JavaScriptの場合、「ブラウザ上で実行する」ってのが前提で。プログラムが間違っていた際に、「ブラウザをクラッシュさせたり」とかを防がなければならない、って背景事情があるのね。
それもあって、「どんなに間違っていても」取り敢えず動く、とかさ(笑)。そういう設計にしてんだよ。だから「動き続ける」んだけど「計算が間違ってても意に介さない」って言う恐ろしい性質を持っている(笑)。その辺がJSの異質なトコだ。
そしてそれが故にプログラムにバグが入り込む事を容易にする。しかも「見つかりづらい」。取り入れられた「例外処理」で扱ってるエラーなんかも、同時期に登場した他言語に比べても異様に少ないのね。本文書で扱ってるError()コンストラクタ、RangeError、TypeErrorの三種で殆どを賄えよ、とか言ってるのと等しいくらい少ない(他は処理系が投げてくるものなんで、ユーザー側が積極的に「使う」事はほぼないだろう)。これも発想としては「エラーを投げる以上、処理系を止めなきゃならない」から、止める要素を少なくしてんだ。ブラウザが固まっても困るだろ、と(笑)。
そして恐ろしい事にJavaScriptにはいわゆるZeroDivisionErrorが存在しない(笑)。ある意味数学的に正しく、1/0なんて計算させた日にゃあinfinityを返してくる、と言う事をやってのけている(笑)。正直これには感心したけれど(笑)。
あとゼロ値自体は変数の初期化がいらんというのはメリットですかね?(真偽チェックに関係ないけど)
さすが、RustとかGo経験すると言う事が違ってくるよなぁ(笑)。そういうメリットはあるかも(笑)。
うん。最初はそれらどうかね、とか思ってたんだけどさ。
昨今、生成AIのせいで、「プログラミングに於いて、簡単に統計の基礎を教えないとなんない」って機運が高まってきていて。
世界標準MIT教科書 Python言語によるプログラミングイントロダクション 第3版とかPythonによるプログラミング入門 東京大学教養学部テキスト 第2版がそういう方針になってて、それは「正しい」のよ。
で、多分「統計的仮説検定」辺りは扱うかな。確率分布関数の実装とかやってさ。JavaScriptでそういう「統計」の話を扱おうと思ってます。その辺基礎知識が欠けた状態で、Pythonみたいに「外部ライブラリさえあればAIなんてすぐ出来る」ってのは甚だ危険だろう、とか僕も思うんでね。龍虎氏がやってくれました、第5弾。
お〜偽値はゼロ値って感じなんですかね。結局こっちのほうが便利かな・・・という気もするなぁ
そういう感想を持つ人もいるんだろうなぁ。
なお、ブログの方にも書いたけど、大体のパターンでは
- 静的型付け言語 => 論理値(true/false)はれっきとしたデータ型になっていて独立している。論理演算は論理値を返すための演算になる。
- 動的型付け言語 => 論理値(true/false)は、偽値(false)以外はデータ型ではない。偽値及びそれに準ずるもののみが偽と判定され、それ以外は真となる。
となっている。
Schemeでは#fが唯一無二の偽、として判定され、その他は全部「自動的に」真と判定される。
んで、論理的にはこれが一番「正しい」んだけど、他の動的型付け言語での「準ずるもののみ」ってのがややこしいし、ここである意味一種の論理破綻が生じる。
JavaScriptの場合、元々の開発者、ブレンダン・アイクが旧ネットスケープ(現Mozilla)の上層部の圧力により(笑)、「Sunが開発中のJavaに似せろ!」ってやらざるを得なかったわけ。Javaハラスメントだ(笑)。
んで、Javaは実は、今見てる通り、静的型付け言語なんで、論理値はキチンとしたデータ型を持ってる。JavaScriptはそうじゃない。
んで、どういうわけか、ブレンダン・アイクは「いい加減な型付け言語」のC言語の様式を、多分「Javaの元ネタなんでいいだろ」ってぇんで混ぜちゃったんだよな(笑)。Cも厳密な意味ではデータ型がない。と言うより数値以外に何もない。で、「0は偽を意味する」ってやってるわけ。それをJavaScriptに持ち込んじゃった。
Javaも既存C/C++ユーザーにアピールするマーケット戦略を持っていて、JavaScriptもそれに則らなきゃなんなかったのね。で、当時のC/C++ユーザーにも「JavaScriptは、ほら、こんなにC/C++に似てますよ〜」ってやんなきゃなんなかった。
まぁ、言っちゃえば「マーケティング上の決定が、言語設計を歪めた」と言う最大の失敗例となっております(笑)。なお、ブログの方にも書いてる通り、ぶっちゃけ、Pythonも失敗してる。反面、Rubyは良く出来ている、ってカンジかしら。
えっ!そういう定義だったのか(今更)・・・
これもねぇ。ぶっちゃけプログラミング言語に於いて「構文が何を意味するか」ってのの厳密な定義がない。
例えばさ。アセンブリ言語レベルでは機械語を模して、
add 1, 2みたいなのが「計算記述ルール」となっている。要は本当の意味での構文だよね。
一方、通常のプログラミング言語で、足し算をやります、とか言った場合、当然1 + 2とか書く。これは「人間にはその方が分かりやすいから」なんだけど、要は元の(アセンブリ言語レベルでの)構文を歪めてるわけなんだよ。
こういう「一つの構文を分かりやすいように別の構文へと変換してる」のを、ご存知、構文糖衣(Syntactic Sugar)とか呼ぶわけなんだけれども。
いや、ここでちょっと待て、って話になるじゃん?そうすると、すべての高級言語で言う「構文」は「構文糖衣」となる。
結果、- 高級言語における構文とは構文糖衣の事になる。
って事だよな。これってトートロジーなんだよ(笑)。しかも。
- 構文糖衣は構文を別の構文へと変換したもの。
となると、こりゃ再帰的定義だ。しかも終了条件がない無限再帰だ(笑)。エロに目覚めた男子小学生が辞書でエロワードを調べた時に起きる現象だ(笑)。
GNUの定義である"GNU is Not Unix"ならシャレたセンス、で済むけど、「プログラミング入門書での解説」でそれはいただけない。
とまぁ、そういう理由で、そう書かざるを得なかった、ってのが本当のところかな。結局、この辺、「人工言語」であるプログラミング言語が、「自然言語」の用語を持ち込んだ場合、どうしても「矛盾が起こる」と言う一例だよな。
うっ!これは一見して全く手に負えない・・と、感じましたが・・1〜5と読み進めるに連れて「あれ?出来そう・・」とみるみる気持ちが変化するのを感じる。
ああ良かった。そう、それが狙いです。
ガーン!こんな簡単な話だったなんて・・
そう、実はプログラミング言語で「数式を転写する」ってのは思ったより難しくない。
と言うより、「すべてのプログラミングの中では実はもっとも簡単だ」って事を書きたかった。
まぁ、アプローチとしては自称「俺は数学が出来る」層には猛反発されるだろうけどね(笑)。なんせ「理解しようとすんな、徹底的に直訳に準じろ」っつってるわけだからさ。
でもいつぞやも書いたけど、実際問題「数学をキチンと理解しろ」とか言う層が言う事って、事実上「全くの役立たず」なんだよ。実行効率0。全く意味がない。
むしろ、直訳を成功させる事自体が自信に繋がるだろうし、「そのうち慣れるだろ」って事なんだよな。なんつったって「単なるパターンとして見ろ」って言ってるだけ、だからさ。
希望としては、この「直訳」に慣れて、片手に数学書、片手にキーボードがあって、バンバン数式をプログラムに翻訳しながら「こういう動作か〜」と「数学を理解する」人が後天的に増えたらな、とか思っておりまする。厳密透過演算子の部分を読んでいて、数値や文字列に対して配列とか関数・・こういう型の大まかな呼び方って無いのかな?と思って質問。ああ、なるほど、プリミティブ!そして対応するその他の大枠をオブジェクトと分類するらしい。が、これも厳密に定義されてはない模様
うん。JavaScript上の独自定義、っつっていいかもしんない。
Type of。ずいぶん初期の頃(だから多分Schemeの頃かな?)にこの型によって分岐するようにしたかったのにType ofが無かったので困った記憶。
そう、Schemeには無いのよね。ANSI Common Lispにはあるんだけど。
この辺、「Schemeがシンプルだ」と言うより、ANSI Common Lispだと、型自体がオブジェクト指向的なヒエラルキーに則って設計されていて、要は、Schemeだと仕様上、原理的にこれを実装するのが難しい、ってな話なんだけどね。
Type ofが成立するには、データ型が構成するヒエラルキー(木構造)を辿ってく必要があるんだけど、Schemeは全然その辺仕様上定義してないからさ。なるほど!毎回「これってどっちの書き方だったかな?」とかやってられないですもんね
そう、やってらんない。少なくとも個人的にはNo, thank you だよな(笑)。
なるほど、こうやってちょっとしたことでも自分が使いやすいようにカスタマイズしていくって事も狙って早い段階でユーティリティの制作を持ってくる構成なわけか〜。どうせなら早い段階でやってしまった方が良いですもんねぇ
そういう事です。狙いはそこだ。それと個人的にはScheme/ANSI Common Lisp関数っぽいライブラリがあったほうが書きやすい、と言う殆どわがままみたいな事情もある(笑)。
JavaScript Scheme ANSI Common Lisp isArray list? listp isEmpty null? null isSymbol symbol? symbolp isString string? stringp isNumber number? numberp どっちにしても、専用述語を作ってた方が利便性は高い、と思うけどね。意味も明確になるし。
なお、これら述語は"C:/Users/PCUSER/javascript/lib/predicates.js"が書き込み先です。"C:/Users/PCUSER/javascript/lib/utils.js"じゃないです。龍虎氏がやってくれました、第4弾。
ありがたや〜ありがたや〜。
お陰で問題文の重複タイピングが見つかった。それも修正しておこう。
やっぱ想定してた通り、問1〜3は簡単だけど、4でちょっと悩むって事になるみたいね。
解答は以下の通り。
4番目は、多分「既にプログラミングが出来る人」なら迷わず代入するだろうね(笑)。
ここまで代入扱ってないから、ちょっと読者は苦労するだろう、と。GPTの解説でVxとVyについては投げた時点でのx,y方向への速度を分解したものだということで一応は納得した、かな。初速にCosったRadianを掛けたらVxが出るってのが神秘だ〜(Vyも)。この程度なので今後が非常に心配だけど、そんなヤツでも大丈夫だ!ってのが狙いであろうから多分大丈夫かな!
うん、大丈夫大丈夫。
この後、「統計関数の実装」とかがネタになるんで、「式を見たら数学的に考えずに直訳しろ」と言うやり方の最初の例、となってるだけ、です。なお、元ネタのもうひとつのScheme入門だと、やっぱ「自由落下くらい常識だろ」って前提で書かれてるんだけど(実は著者の紫藤さんは化学者で、バリバリの理系だ)、それを事細かに分解して、「数学的考察を全く必要としない」辺りまで落とし込んだつもりです。
そもそも、例えばiPhoneなんかだとAppleの審査がある、とか言ってるんだけど、1IT企業がリソース割いて広告審査する、なんて無理なんだよな。
無料ゲームがホント酷い広告だらけで(笑)。なんか塗ればシワ・タルミが取れる、とか言う広告とか、「特殊メイクを溶剤で剥がしてるだけなんじゃない?」とかツッコミどころ満載の広告が良く流れてきてて爆死していた(笑)。無理でしょ、そんなの、とか。
あるいは「テレビ番組✗✗で紹介された」とか書いてるんだけど、そのテレビ番組が存在しない、とかさ(笑)。ビミョーにタイトル変えてたりして、まぁ酷いのなんのって。
Appleって「審査する」とか言ってても実際は「審査出来ない」んだよ。それだけの人員もないし。本業に差し支えあるし。
いずれにせよ、この手の無料広告に辟易して、iPhoneにゲームインストールしてプレイするのを止めました(笑)。あまりに酷い。ネットスラングじゃないの?
いや、その「が強い」ってのが。
「思想が強い」と言う全表現じゃなくって。
例えばDTMに関して「Mixが強い」とか言う言い方が頻出してたりするし・・・・・・。
で、具体的な意味はよう分からんのよね(笑)。
多分類似表現なんじゃないか、って思うんですが。龍虎氏がやってくれました、第3弾。
ここも基本的に問題がなかったようで、ホッとする。
Visual Studio Code+Denoの挙動以外はな(怒
多分、ぶっちゃけ、OSの入力制御かなんかにナニカが取られてる可能性があるなぁ・・・・・・。なんかWindows版とUbuntu版の挙動にも差が見られるんで、多分そういったトコなんじゃなかろうか。
この辺、ちょっと後で精査しとかないといけないかも。
ええっ!?Racketだけの変態仕様じゃ無かったのか・・
うん、この辺、実はECMAScript仕様上、かなりモダンで「変態仕様」になってます。 > JS
ちなみに、この辺も、従来のJavaScript入門的な?本では殆ど記述がない辺りなんですよねぇ。
以前、もとこんぐさんがさ。プログラミング入門的なナニカで、
var tuki = 10;とか
var suuji = 0;とか。そういうローマ字で変数名を書くのが嫌だ、って話をしていて(笑)。
「すんげぇ良く分かる」とか思って(笑)。読者を馬鹿にしてんのか!?とか思う事が多かったの。
「日本語の方が分かりやすいだろ」ってのは分かるんだけど、だったら変数名とか、日本語で書ける、って何で書かないんだ?とか以前から謎だったのね。
と言うか、恐らく仕様を確認してないんだ。いわゆる「プログラミング入門」を書いてる連中は。かなりの部分を「思い込みで」流してる、ってのが実際なんだよ。
上の例でもJavaScriptっつーか、ECMAScript仕様上、
var 月 = 10; var 数値 = 0;ってぇので全く問題がない。ここで「プログラミングではアルファベットを使うのが常識で・・・」ってのは余計なお世話なんだよね。「仕様上出来る」って事を妨害する理由は何一つないんだ。
だから「日本語で関数名を付けたい」って人に対しては「全く否定しない」と言う立場を取った。だって仕様上O.K.なんだもん、って立場です。「禁止されてない事はやって良いんだ」と。
余談だけど、RacketとかSBCLなんかだと絵文字さえ関数名や変数名にする事が出来ます。「それを狙ってた」んじゃなくって、やっぱLisp系のパージングがラクだから、ってぇんだろうね。規則さえ制定されていれば特に言語実装上、追加必要なく、UTF-16とかキチンと解釈出来るようになっている。
この辺の変数名/関数名の「付け方の自由度」ってのはいまだLisp系言語が他の追従を許さないトコです。あ、キャメルケースって先頭小文字だったのか・・
あ、先頭大文字のヴァージョンもある。アッパーキャメルケースとか呼ばれる事もあるんだけど、多分パスカルケースって呼び方の方が通りがいいんじゃないのかな。
それで、恐らく通例だと、パスカルケースでの命名ってのはクラス名とか、ユーザー定義型データの命名規則になってる例が多いんじゃないか、とか思う。
多分。
つまり、関数名の場合はキャメルケース、
function camelCase(args ...) { ... }んで、クラス名の場合はパスカルケース
class PascalCase {constructor(...args) {...} ... }ってパターンが多いんじゃないかな。
前からちょっと気になってしまったので一応・・挿入された画像ファイルの違和感がハンパないですね(_;)
そうねぇ(苦笑)。
まぁ、TeXStudioのデフォ画像サイズは0.7なんだけど、今んトコどうすればいいのか分からんので1.0に拡大してるのが一つの原因かもしんない。0.7に今後戻す事はアリ、かも。
でもホンマ、画像なんとかなんねぇのかな、とか思ってます。
グラフ構造とかだったらGraphvizで何とかなるんだけど、コード解説のための色付けとか?うん、その辺結構大変だったりする。
GIMPも使いづれぇしなぁ。なんか解決策あっかなぁ。コピペでコードのインデントが崩れたりするのも困るし。ハァ。LaTeXでsvgを取り扱うのも難しいっぽいし。
マジでLaTeXはクソだ。ハゲソフトだ。
えっ!もうモジュールに!?これは思想出てますねぇ(小さな関数でユーティリティを作るのだ、という)。
わはははは(笑)。
いや、本当にいわゆる「プログラミング入門」で「ライブラリ作ろうぜ」ってのねぇんだよな。実用的には「そこが一番重要な筈」なのに(実はLisp系書籍にもないんで、このアプローチは「限りなく世界初」かもしんない)。
ホントさらっと流してる。
だから一つ、差別化の為に徹底的にそれをやる、って事にしています。
基本的にこの時点でのutils.jsは次のようになってます。
function rest(array) { return array.slice(1); } function add1(x) { return x + 1; } function sub1(x) { return x - 1; } function first(array) { return array.at(0); } function second(array) { return array.at(1); } function third(array) { return array.at(2); } function fourth(array) { return array.at(3); } function fifth(array) { return array.at(4); } function sixth(array) { return array.at(5); } function seventh(array) { return array.at(6); } function eighth(array) { return array.at(7); } function ninth(array) { return array.at(8); } function tenth(array) { return array.at(9); } function last(array) { return array.at(-1); } function lastArray(array) { return array.slice(-1); } export { add1, eighth, fifth, first, fourth, last, lastArray, ninth, rest, second, seventh, sixth, sub1, tenth, third, };lastArrayに関してはArray.prototype.slice()の利用かな。
ちなみに、この辺のユーティリティは全部Scheme/Racket/ANSI Common Lispから持ってきています(笑)。
んで、これ出来るのも、仕様上、JavaScriptって「標準ライブラリって言うほどユーティリティが揃ってない」って事があるのよね。Webブラウザで動かす以上、ある種ミニマリスティックな言語なんだよ。
だから「宿題出しやすい」言語なんだって(笑)。 > JS
こういうアプローチって、PythonやRubyじゃ出来ないからね。あいつら何でも抱えてるんで、実はコンピュータ・サイエンス的な宿題出すにはあんま適してないプログラミング言語なんだ。
*は正規表現的なAllかな?
そうですね。
まぁ、まだ
性器正規表現やってないからな。文字列の章で扱うつもりなんだけど。基本的なトコを。うおお変数束縛の書き方が分からんw(参考になるように他に参照しないでやってますが・・ここまで既に束縛解説あったらすいません)。そしてもしかしたらMathで円周率あったらすいません
そう、そこはMath.PIだ。
実はもう結構、解答例も作ってんだけど、PNGとして独立して、・・・ってのが面倒くさくてね。
そして、実はかなり解答も丁寧に「どうしてそういう風な書き方してるのか」とか説明してんだ。数研のチャート式くらいには丁寧に書こう、ってぇんで苦労してます。
「コード例だけ挙げる」ってやっても役に立たんだろう、ってぇんで、その辺も結構神経使ってるかなぁ。
龍虎氏がやってくれました、第2弾。
ありがたや〜ありがたや〜。
取り敢えず三章には問題がなかった模様。
ホッと胸を撫で下ろした也。
なお、龍虎氏の
なんとなく関数の引数に取れるデータってイメージをしてたなぁ
ってのは正しい。もっと言うと、「変数にそのまま代入して使い回せる/関数の引数/返り値として使えるデータ型」と言うのを第一級オブジェクト(first-class object: ファーストクラスオブジェクト)と言う。
「そのまま定義書けば・・・?」と言われるかもしれんが、ここまで代入も変数も扱っていない(笑)。
まぁ、そういった理由で苦肉の策として順次定義をアップデートしていって・・・と言う方針にしています。
「暫定的」っちゅうのはそういう意味ね。なお、例えばC言語だと配列さえファーストクラスオブジェクトじゃない。配列は変数に代入出来ない。配列は関数の引数にも返り値にも出来ない。
Cだと「配列の先頭を指すポインタ」を変数に代入する事は可能だし、関数の引数/返り値を「配列の先頭を指すポインタ」にする事は出来る。
出来るんだけど、それは「配列そのもの」と言ったデータ型ではない。あくまで「先頭を指すポインタ」なんだ。
従って、C言語では配列はファーストクラスオブジェクトではない。
同様に、「関数ポインタ」でやり取りは可能だけど、「関数そのもの」ではない。だからCに於いては関数はファーストクラスオブジェクトではなくなる。普通はケツから出たものを次の奴が飲み込むって方が自然に感じられるでしょうね
Euphoriaか(違
あー、要はそこをちゃんと……GUIなら例えば、ボタン押したら手続きが始まって、って言うのがずっと分からなくて、それでGUIが分からないままだったんです。
なるほど。
それはね。理論的な話をすると、Smalltalk型オブジェクト指向で言うトコのメッセージパッシングなんだ。
「ボタン押したら手続きが始まって」と言うより、「ボタンを押した、ってメッセージが特定のオブジェクトに向かって送信される」ってシステムだね。
まぁ、この辺隠蔽されてたり、ってのもあるんだけど、例えばGUIツールキットの一つ、GTK+なんかだとモロにこの「メッセージ送信」システムになってて、使われてるAPIがコールバック関数の嵐になってたりします(笑)。
転機になったのが必要に応じてGASを書きたいとか、ちょっとしたJavaScriptのアプリを作らないと、ってなったときにその中でならオブジェクト指向のやり方が分かったので、「あっじゃあオブジェクトで考えればいいんだ、今ならGUI分かりそうだよね」という動機のままほったらかしてるんです。
ちなみに、JavaScriptは現在、GUIだとひょっとしたらアタマ一つ抜けてるかも、ってのがあって。
元々、確かにGUIは歴史的に代表的なオブジェクト指向言語の一つ、Smalltalkから出てきた。
ところがね。GUI = オブジェクト指向、ではない。僕らがGUIでオブジェクト指向をやらなければならない、ってのは、どっちかっつーとGUIツールキットの類がオブジェクト指向で組まれてるから、なんだ。僕らは「ツールに合わせて」ひょっとしたらオブジェクト指向を使わざるを得なくなってる、っつーか「付き合わざるを得ない」状況になってるかも、なんだ。単純に言うと、ウィンドウを始めとするウィジェット、ってのが階層構造を要してて、GUIツールキットを「作ってる側」ってのがオブジェクト指向だと継承がやりやすくて、個々のウィジェットの定義が簡単になる、って事が重要になってんのね。「こちらがわの理由」と言うより「あっちがわの理由」ってのが実は大きい。「オブジェクト指向が万人にとって便利だから」じゃないんだよ(笑)。
ところで、かなりの率で、例えば「ウィジェットの階層構造を保存する際に」、GUIの「状態」を保存するんじゃなくって、「階層構造」をXMLで保存するケースが多い。GUIツールキットはそのXMLファイルを読み出して解析、再構成してGUIのウィジェットを作り出す。
ところが、JavaScriptユーザーの誰かが、「どうせXMLに保存するならHTML使えば良くね?元々ブラウザ用言語だしさ」とか思いついたらしい(笑)。つまり、GUI部品をGUIビルダなんかで「自動コーディング」で作るんじゃなくって、「デザイン観点」から始めっからHTML + CSSでやればエエんちゃうの?とか思いついたんだよな(笑)。
しかも、サーバーサイドJavaScriptとかカッコつけて言うけれど、事実上「JavaScriptでデスクトップアプリを作る」って前提で考えるなら、「端末で走らせないでブラウザで走らせれば良くね?そうすれば、GUIの要求って満たせるじゃん」みたいになっちゃった。
このアプローチでの最大の成功例が実はVisual Studio Codeで。これ、実はNode.jsで作られてるんだけど、使ってるGUIライブラリをElectronつって、実はこいつは本体内にGoogle ChromiumってWebブラウザを抱えてて、そいつをカスタマイズする事に特化してGUIアプリを作るようになってんだ。
結果、Visual Studio Codeの正体は実はGoogle Chromiumだ。
この辺のアプローチは結構革新的で、Google V8を利用した処理系、Denoなんかにも受け継がれていて、さすがにGoogle Chromiumみたいに丸ごとWebブラウザを端末代わりに使う、的なアプローチはやめてるんだけど、HTML +CSSでGUIアプリを作ろうぜ、って流れはどんどん加速しています。
HTML+CSSだったら従来のGUIツールキットに比べてもGUIアプリのデザインが面倒くさくない。JSは基本的にそっちの方に舵を切ってて、割に先進的な状態へと突き進んでる、ってカンジかな。
そうすると、必ずしもオブジェクト指向でやらなくてもいいわけで、JavaScript「だけ」は既存のアプローチと違う道を歩んでいきそうです(逆に、例えば従来のwxWidgetsみたいなGUIツールキットへのバインディングみたいなのが、JS界隈では極端に人気が落ちている)。
お恥ずかしながら……。
そうですか。
ええとね、概要だけ。
Read-Eval-Print Loop(REPL)ってのはインタプリタ実装法ってので有名なんだけど、単純には、ソフトウェアを作る時、「読み込み部」「評価部」「出力部」をバラバラに作って、それらを組み合わせましょう、って言う設計提言なんだ。考えてみると、例えばExcelみたいなソフトもそうでしょ?必ず入力/計算(評価)/表示、ってプロセスがグルグル回ってる。ワープロもそうだし、ゲームもそう。
あらゆるソフトウェアは基本的にRead-Eval-Print Loopって構造になってるんだ。
って事は「ソフトウェアを設計する際には」入力、評価、出力、とパーツをバラバラにして設計した方が良い、って話になる。「動作」に設計の最初から則る、って事だよね。それが基本。
んで、CLIのソフトウェアを書く場合、基本、入力関数、評価関数、出力関数の組み合わせになるわけだけれども。
GUIの場合、このREPLの部品それぞれをクラスでラップしてやる。入力関数 => Controllerクラス、評価関数 => Modelクラス、出力関数 => Viewクラス、となる。
これらを組み合わせるのをModel-View-Controller(MVC)って言うんだ。つまり、REPLって設計方針でまずはCLIのソフトウェアを作っておいて、その構造のままで各部品をクラスでラップして、M、V、Cにしちゃう。あとは、GUIツールキットに依るんだけど、例えばGUImainloopとか?そこにModel、View、Controllerのインスタンスぶちこんでループさせればあっという間にGUIアプリの出来上がり、と。
理屈はそういう事になるね。悩む必要がなくなる。
ただ、問題はツールキット側が基本「MVCを想定してない」って事が良くあってさ。別途ライブラリが必要になる、って局面はあるかな。
例えばPythonの場合、wxPythonとかあるいはPySideとかと別に、Pypubsubみたいなライブラリを使った方が良い、って話になる。デザインパターンを学んだ事あるかどうか分からないけど、出版-購読型モデルと呼ばれるパターンだね。こいつがあれば、M、V、Cの各インスタンス同士でメッセージを送り合い、先程の「理屈」を簡単に実装出来るようになる。多分探せばC++にもそういう外部ライブラリがあるんじゃないかしらん。
ちなみに、こういうGUIの構成法ってSmalltalkってプログラミング言語が始めたもので、別にヘンなやり方じゃなくって、本当は「スタンダードなやり方」なんだ。
一方、MS-DOS/Windowsだと、GUIのガワに「スクリプトぶら下げて」ってモデルを・・・多分初代Visual Basicとか、あるいはTurbo Pascal/Delphiが広めちゃって、「スパゲティコードを作るのがGUIのお作法」になっちゃったのね。
だから僕らみたいな後続連中がクッソ悩む羽目になる、と言う(笑)。昔のRADのスタイルだと「スパゲティになるためにコードを書く」ってなって当たり前なんだよ(笑)。だから「GUIはクソややこしい」って話になっちゃうわけ。
いずれにせよ、ここで理論的に言ってる事、ってのは、「CLIのソフトウェアを書けるなら、その構造のままでGUIに持ってこれるよ」ってお話です。
龍虎氏の記事のお陰で修正箇所が分かった。
settings.jsonだが、現時点でのDeno+Visual Studio Codeだと、{ "deno.enable": true, "deno.lint": true, // これを true にすると、書き方のマナーを教えてくれる "deno.unstable": [], // 実験的な機能(ノイズ)を完全にシャットアウト "js/ts.suggest.completeFunctionCalls": true // 関数補完を少し親切にする }になる模様。
deno.unstableは現時点、true/falseではなく、配列で細かく実験的機能の制御が出来るらしく、結果、「完全にシャットアウト」する際には空配列を与えるように改変されたらしい。最近は落ち着いたけど、それでもDeno+Visual Studio Codeのアップグレードの速度は早く、今後とも要修正が起きるかもしんない。
龍虎氏がやってくれました。
いや、ジェバンニじゃねぇんだけど(謎プログラミング学習日記「CametanさんのJavaScriptによるモダンなプログラミング入門(仮)ドラフトでリハビリOn Omarchy第1回」 二章まで行く
ありがたや、ありがたや。
さて。
とか言いつつ・・マニュアルではWindows使用が前提となっているのに、いきなりLinux環境(Omarchy)でやってしまう。
かまへんかまへん。
実際、僕も原稿書いたりコード書いたりしてるのはLinuxなんでね・・・(笑)。
そう、実は「Windows用」って書いてるのは、あくまでパンピー向けだったりする。入門で使われていたChocolatelyはどうすれば?と質問したところWindows用のパッケージマネージャだと判明。
そうそう。
要は、例えばDebian系ディストリビューションだとaptに当たるのがWindowsのChocolately。あるいは、Macで言うHomebrewか。
いずれにせよ、差異はこの辺だけ、で、Visual Studio CodeもDenoもクロスプラットフォームである以上、差はそんなに無い、ってのが事実です。なお、最近主流になりつつある、Microsoft公式のWingetに差し替えようか、とか思ったんだけど、今のとこ、使い勝手が上なのは結果Chocolatelyなんで、現行のままで行こうかな、って思っています。
(Wingetは色々、GUIと同様なポップアップが現れたりしてウザい。)サジェストの設定ではより新しいサービス?があるようでアラートが出た
あら。
差し替えておきましょうか。
Denoも最近は落ち着いてきたんだけど、アップグレード早ぇからなぁ・・・・・・。
通常の計算は出来るけど、作った関数を利用したものは存在しないと蹴られてしまった。
多分スクリーンショットを見る限り、Ctrl + Aしてないかな。Jupyterのプロンプト番号が1になってる。
hoge.js側がアクティブな状態で、Ctrl + Aして【すべてを選択】、そこで、第1章通りに設定してたらAlt-X Alt-Eです。
数ヶ月前Antigravity2.0が発表されたときにIDEが入れられなくなって放置していたけど、現在どうなってるのか?と。そもそもプログラミング学習を一時停止した理由の一つがこれだったからな・・。
あらま。
なお、Antigravityって実はVisual Studio Codeの改造版で、そのVisual Studio CodeはGoogle Chromiumの改造版で・・・・・・。
何キミら二人でキャッキャウフフしとんねん(謎
ってなわけで、そのままAntigravityでイケるんじゃないか・・・?とか思ってたんだけど。
ダメか。死んでたかキミ。