2026年9月1日火曜日

EXCELの表をKaTeX形式に変換するマクロ

生成AI時代にプログラミング言語を学習する必要はあるのか?

最近では生成AIがプログラムを作成する時代になってきましたが、そんな時代にプログラミング言語を学習する必要はあるのでしょうか?

ということで早速 Google さんに聞いてみました。

生成AI時代にプログラミング言語を学習する必要はあるのか?

 答えは

生成AIがコードを自動生成する時代においても、プログラミング言語の学習は不要になるどころか、AIの出力を正しく理解して使いこなすために重要です。
  • コードを「読む力(読解力)」が不可欠になる
  • 適切な指示(プロンプト)を出すため
  • エラーやトラブルへの対応

 ということで学習の仕方も変わるようです。

  • 「書く」から「理解する・指示する」へ:
    文法を細かく暗記してゼロからコードを打ち込む作業はAIが担うため、全体像を組み立てるプログラミング的思考や構造の理解が重視されるようになっています。
  • 作りながら学ぶ:
    あらかじめ言語を完璧にマスターするのではなく、まずは作りたいものをAIと一緒に形にし、その過程で必要な知識を補うアプローチが効果的です。

とは言え巷にあふれるプログラミング言語の学習書ではやはり文法が優先しているように思います。確かに本としてまとめるには一番書きやすい形式ではないかと思います。

実際にPythonを教えている身としては、教えやすいので文法から入るという流れで教えているのが現状です。ただ、最近はデータ形式を中心に教えるようにして、文法はその流れの中で教えるという方向にしています。Pythonは静的型付け言語ではありませんが、プログラムを作成する上でやはりデータ型を考慮する場面が出てきます。

例えば、inputで入力したデータは数値変換しないと計算には使えない。

小学校でも2020年度から「プログラミング的思考」を教えるようになり、その後、順次中学校、高校へと進み2025年1月の大学共通テストからは科目「情報」が追加され、国公立大学を受験する際は、原則として「情報Ⅰ」の受験が必要となりました。
内容的にはプログラミングを全面に出すというよりも、情報に関する覚えておくべき知識が網羅されているように感じます。

そこで、最近始めたのですがnoteでPython初心者向けの記事を投稿し始めました。
システム開発のV字モデルをベースに、アルゴロジックというゲームを攻略するアプリの開発を行うというストーリーで話を進めています。
まずは、要求仕様から考えて、必要なプログラムの詳細仕様書を作成する流れで、その中でPythonの知識を学習していくという流れで進めています。

note(ノート)には表の挿入機能がない

noteはシンプルなデザインで簡単に文章や画像、音声などを誰でも簡単につくって公開できるメディアプラットフォームです。HTMLも一部使用できるものもありますがtableタグについては使用できないようです。

いろいろと調べるとKaTeX(カテフ)を使って数式や擬似的な表などを表示できるようになっています。ただ、KaTeXの表記方法は面倒なのでEXCELで表を作成してそれをKaTeX形式に変換してクリップボードへコピーするVBAを作成しました。

noteがシンプルなデザインを基本としているので表も単純でシンプルな形式のみを対象として、セルの連結や複雑な罫線なども対象外としています。
EXCELの表をKaTeX形式に変換してくれるサイト(Tables Generatorなど)もあるようですが、note専用の生成ツールとして生成AIに作ってもらいました。


'=== 文字列をクリップボードへコピー ===
Private Sub CopyToClipboard(ByVal s As String)
' DataObjectの作成(遅延バインディング)
    Set myData = CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
    
    ' クリップボードにテキストを設定
    myData.SetText s
    myData.PutInClipboard
    
    MsgBox "LaTeX形式の表をクリップボードにコピーしました。", vbInformation
End Sub

'=== Excel範囲 → KaTeX表変換 ===
Sub RangeToKaTeXtop()
    Dim rng As Range
    Dim r As Range, c As Range
    Dim latex As String
    Dim cols As Long
    Dim rowText As String
    
    Set rng = Selection
    cols = rng.Columns.Count
    
    latex = "$$" & vbCrLf
    latex = latex & "\newcommand{\arraystretch}{1.3} %" & vbCrLf
    latex = latex & "\begin{array}{" & WorksheetFunction.Rept("|l", cols) & "|}" & " \\\\[-1.4em]\hline" & vbCrLf
    
    For Each r In rng.Rows
        rowText = ""
        For Each c In r.Cells
        If c.HorizontalAlignment = xlCenter Then
            rowText = rowText & "\hspace{2px} "
        End If
        rowText = rowText & "\text{" & c.Value & "} & "
        Next c
        rowText = Left(rowText, Len(rowText) - 3)
        latex = latex & rowText & " \\\\" & " \hline"
        If r.Row = 1 Then
            latex = latex & " \\[-1.4em]\hline"
        End If
        latex = latex & vbCrLf
    Next r
    
    latex = latex & "\end{array}" & vbCrLf
    latex = latex & "$$"
    
    CopyToClipboard latex
    
End Sub

2026年3月1日日曜日

Google Blogerにコピーボタン(execCommand不使用)を追加しました。

 日本ではBlogerが不人気なようです。

完全無料、広告表示なし、https標準対応、25年以上継続的に運用されてきたサービスなんですが、日本では使っている人が少ないようです。
とりあえず始めるのは簡単で、カスタマイズしようと思えば知識は必要ですが可能という強力なサービスだと思うのですが利用者は増えていないようです。

カスタマイズも最近でしたら生成AIがあるのでHTMLやCSS、Javascriptもあまり知識がない私のような者でもそこそ出来るようになってきました。

という事で、今回コードブロックの右側にコピーボタンを配置し、クリックするとコードをコピーできる機能を実装してみました。ただし、execCommand については非推奨になりましたので代替案であるHTML5のClipboard API を使用した形で実装したいと思います。
まずはGoogleさんで検索をして幾つかのサイトを参考に実装してみました。
私のサイトではソースの表示にはprettyprintを使っているのですが、linenumsを指定するとうまくコピーできない(1行目だけコピーされる)ようです。

原因は、linenumsを指定するとol、liダグを使って行番号を表示させているのですがこれが原因のようです。

という事でCopilotに指導を仰ぎながら修正したのが以下のコードとなります。

CSS

Blogerのテーマ > マイテーマの「HTML編集」で「]]></b:skin>」の前に以下のCSSを追加して下さい。

pre.prettyprint {
  overflow: auto;
  word-wrap: normal;
  text-align: left;
  margin: 0;
}
pre.prettyprint > ol.linenums > li
{
  list-style-type: decimal;
  margin: 0;
  padding: 0;
}
.code-container {
  text-align: right;
  margin: 0;
}
.copy-button{
  font-size: 12px;
  padding: 2px 10px;
  color: #fff;
  background-color: #444;
  border: none;
  cursor: pointer;
  transition: background-color 0.3s ease;
}
.copy-button:hover{
  background: #999
}
pre code{
  display: block;
  margin: 0;
  padding: 2px 5px;
  line-height: 1;
  overflow: auto;
  color: #f8f8f8;
}

Javascript

同じく、「/body」の直前に以下のコードを追加して下さい。

  <script>//<![CDATA[
    // コピーボタン作成用コード
    (function(d){
        const pres = d.querySelectorAll('pre.prettyprint');
        if(pres.length == 0){
          return;
        }
        pres.forEach(function(pre) {
          // コード(pre)とCopyボタンを収容するdiv作成(Copyボタンにprettyprintの影響が及ばないようにする為)
          const div = d.createElement("div");
          div.className = "code-container";
          // Copyボタンを生成してdivに追加(子の先頭)
          const btn = d.createElement('button');
          btn.className = 'copy-button';
          btn.textContent = 'copy';
          div.appendChild(btn);
          btn.addEventListener('click', copy_code, false);
          // コード(pre)の親にdivを追加
          pre.parentNode.insertBefore(div, pre);
          // コード(pre)を現在の親からdivの子の末尾へ移動)
          div.appendChild(pre);
        });
    })(document);

    // コピー機能用コード
    function copy_code(){
      const pre = this.nextElementSibling;
      let code;
      if(pre.classList.contains('linenums')){
        code = [ ... pre.querySelectorAll('li')]
          .map(li => li.textContent)
          .join('\n');	  
      } else{
        code = pre.textContent;
      }
      if(navigator.clipboard){
        navigator.clipboard.writeText(code).then(() => {
          this.textContent = 'Copied';
          setTimeout(() => {
            this.textContent = 'Copy';
          }, 500);
        }).catch(e => {
          alert('コピーできませんでした\nお手数ですが手動でコピーしてください\n\n' + e.message);
        });
      } else{
        alert('このブラウザは Clipboard API 非対応です\nお手数ですが手動でコピーしてください');
      }
    }
  //]]></script>

あとはprettyprintを使ってコードを埋め込めば、自動的にCopyボタンが追加されます。

今回参考にさせていただいたサイト
コードブロックにコピーボタンを実装する(Clipboard API 対応版)
Bloggerでコードをきれいに表示する方法-copy機能の追加

2026年2月26日木曜日

Raspberry Pi 500+ 日本語配列版はほぼパソコン

Raspberry Pi 500+ 日本語配列版をポチってしまいました。 

Raspberry Pi 500+は2025年9月25日に発表されましたが、そのキーボードを日本語版にして16GBメモリに256GB SSD持つキーボード一体型のRaspberry Pi 5 になります。
その詳細はこちらに詳しく紹介されているので見て下さい。

自宅に来た、Raspberry Pi 500+を早速試してみました。
数値的なものよりも体感的にどう感じるかで評価したいと思いますのでブラウザを使って試したいと思います。標準でChromiumとFirefoxが入っていて初回起動時に選択ができるようになっていました。
Raspberry Pi 4はmicroSD、Raspberry Pi 5はSSDからの起動となります。

2回目以降起動時ChromiumFirefox
Raspberry Pi 4/8GB4.238.89
Raspberry Pi 500+/16GB1.484.29

追記:2026/02/27
初回起動時の測定も行なってみました。
SSDの威力が発揮されている結果となりました。

初回起動時ChromiumFirefox
Raspberry Pi 4/8GB12.7118.25
Raspberry Pi 500+/16GB2.766.5

初回起動時はライブラリの読み込みなどで時間がかかるので、数回起動してから測定を行なっています。電源投入後の初回は2,3秒microSDでは8秒〜10秒、SSDでは1、2秒時間が多くかかるようです。
注目すべきはRaspberry Pi 500+でのChromiumでほぼ瞬間で起動される印象です。

そのお値段ですが、本体+公式マウス+公式ACアダプターで約53,000円(秋月電子通商)でした。これに公式ディスプレーを付けると約73,000円ですが、すでにディスプレーを持っていたり、リビングのTVを使うなら5万円ちょっとです。

しばらく使ってみてちょっと不満なのは、電源ボタンがDeleteキーのすぐ横にあるので、Deleteキーを多用する身としては誤って電源ボタンを押して、ログアウトダイアログボックスが表示されるのが面倒なのと、キー音がちょと耳障りな事でしょうか。

Chromiumを快適に使うちょっとした作業

Raspberry PiといえばChromiumですが、実はRaspberry Pi OSがBookwormになってからChromiumで日本語入力ができないという現象が出ていました。そのあたりの詳細はこちらに詳しいのですが、ここではとりあえずどうすれば解消できるかだけ纏めておきたいと思います。

STEP1: fcitxをfcitx5に変更する。

標準では fcitx-mozc がインストールされていますが、これを fcitx5-mozc にインストールし直すと共に、日本語フォントもインストールしておきます。
Terminalを開いて以下のコマンドを順次実行して下さい。

sudo apt update
sudo apt install fcitx5-mozc fcitx5-config-qt -y
sudo apt install fonts-noto-cjk fonts-ipafont -y

STEP2: Wayland用にChromiumを設定する。

これでChromiumで日本語入力は可能ですが、変換ポップアップがおかしな場所に表示される問題があるのでこの対策を行います。

具体的には /etc/chromium.d/10-gtk-version ファイルを作成して以下の内容を追加します。

<実行コマンド>

sudo nano /etc/chromium.d/10-gtk-version

<追加内容>

if [ ! "$XDG_SESSION_TYPE" = "x11" ]; then
    export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --gtk-version=4"
fi

編集を保存して終了するには、Ctrl+o、Enter、Ctrl+x の順にキー入力します。

STEP3: Fcitx5 をデフォルトに設定

以下のコマンドを実行して、再起動すれば Chromium で日本語入力が問題なく出来る様になります。

im-config -n fcitx5


2026年2月21日土曜日

Windows11でALT+Shift+PRT SCでウインドウのスクショが取れなかった件

久々の投稿です

2年程ご無沙汰しておりました。
元々、筆不精者が仕事が忙しくて物書きが全くできませんでした。ひと段落着いたのでまた書きたいと思います。
今回は投稿の為にWindows11で画面のスクショを撮ろうとしたら、ハイコントラストのショートカットとバッティングしていてスクショが取れなかったというお話です。

Windows11でALT+PRT SCはアクティブウインドウのみをスクショする為のショートカット何ですが、私のノートパソコンでは当該キーがSCR LK(スクロールロック)と共同となっていてALT+PRT SCの為にはALT+Shift+PRT SCとする必要があることからハイコントラストのショートカットと重複してしまったという事です。

解決策

ハイコントラストのショートカットを無効にする事で対応しました。

  1. 「設定」アプリを開きます(Windowsキー + I)。
  2. 左側のメニューから「アクセシビリティ」をクリックします。
  3. 「コントラスト テーマ」を選択します。
  4. 「コントラスト テーマのキーボード ショートカット」という項目を探し、スイッチを「オフ」にします。


2023年8月11日金曜日

Edisonが故障した一件

 最近またEdisonで遊んでいます。


教育用のデバイスとしてよく出来ているなと思っているEdisonですが、現在3台を所有しています。
最近このうちの1台が調子が悪くなってしましました。具体的にはBeep用のデバイスが壊れたようです。購入時にチェックをしたつもりですが今回久々に音関係のプログラムを作っていたところ音が出なくなっていました。
通常は電源を入れるとBeep音が鳴るのですがこれが出ないのでおかしいなと思って、とりあえずプログラムを作って動かした所やはり音が出ませんでした。

あれ、Blogerのプレビューが動かない!


これはMacBook Airで書いて居るのですが、今までプレビューも問題なく使えていましたが今日は「読み込んでいます」でループして居るようです。
とりあえずiMacに移って続きを書き始めましたが、こちらでは問題無くプレビューできるようです。
私のMacBook AirもEarly 2015と既に8年前の物、最近ではシステムアップデートもできていませんし、バッテリーもお亡くなり寸前の状態です。そろそろ買い替えたいなと考えていますが、今のところ動いているので延び延びになっています。
来年あたりは変えかられるかなぁ〜

閑話休題


早速、サポートに連絡を入れましたがレスポンスも翌日にはあり、その後も丁寧に対応してくれました。非常に好感が持てましたので嬉しくなってアップした次第です。5、6回のやりとりをしましたが、概ね翌日の午前中にはレスポンスがあリました。アーストラリアとは2時間の時差なので、向こうで朝一メールをチェックして対応しているのかなと言う感じでした。

やはり、ブザーデバイスの故障ということになり、保証期間内なので代替品を送ってもらえることになりました。

保証期間は1年間あるのですが、これもしっかりとした物作りができていると言う自信なのでしょうか? Edisonそのものは非常にコンパクトでしっかりとした作りになっています。小さいお子さんも使う前提で小さな部品もほぼ無く(電池カバーのみ)鋭角な部分も少なく安全にも配慮された作りになっていると思います。 LEGOと組み合わせることができるので、レゴを使った場合には小さなお子さんがLEGOブロックを飲み込む危険があるので注意が必要にはなります。
製造は中国で行っているようですが、今まで問題になったのは電池ボックスの蓋のバネが弱くて電池がうまく接触しなかったケースぐらいです。これもバネを少し伸ばしてあげることで問題なく使えるようになりました。

マイナス点としては、電源スイッチが非常に小さいので小さなお子さんでは電源を入れられないかもしれないと言う点。
あとは、電池ボックスの蓋がちょっと癖があるので開け閉めにコツがいることでしょうか。これはホームページのFAQにも対策が書いてありました。

Edisonドキュメントの日本語化を進めています


EdisonはEdBlock(Scratch Jr)、EdScratch(Scratch)、EdPy(Python)と理解に応じた言語が用意されているので年長さんあたりから中学生あたりまで広くプログラミングの学習に使えるなと考えています。
ただ、問題は日本語ドキュメントが無いのがネックになっていると思います。上記3つの言語ツールも全て英語版だけなのでそこが利用する上でのネックになっているのかと思います。
本体は6千円程度で入手できるのでLEGOと比べると購入しやすいと思います。

と言うことで、現在プログラミング学習用ドキュメントの日本語化を進めています。
本家が非常に良質なプログラミング学習用ドキュメントを用意してくれていて、翻訳したいと連絡したら翻訳用キットを送ってもらえました。
現在、鋭意翻訳中ですので終了しましたら公開していきたいと考えています。
1人でやっているので時間がかかりますが、まずは生徒用ドキュメントから翻訳を始めています。

今しばらくお待ちくださいね。

2023年4月7日金曜日

ESP32をW5500で有線LAN接続してmDNSしてみた -2-

前回投稿より1年近くが経ってしまいました。途中、投稿しとこうかと思った事も幾つかあったのですが、ついついコードを書く事が優先して気がつくと何を書こうとしたのかも忘れてしまう有様でした。
そろそろボケが入って来たのかな?

W5500搭載 ATOM PoEキット


現在IoT 関連のプログラムを趣味のように書いていますが、その中でこんな物を見つけたのでWi-Fiが使えない&電源を取るのが難しいという状況でセンサーが使えそうだなということで早速購入して遊んでみました。

W5500については以前ブログにアップしていたので簡単に動くかと思ったのですが・・・

当時のplatformio.iniは
[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
lib_deps = 
	adafruit/Ethernet2@^1.0.4
	khoih.prog/MDNS_Generic@^1.0.1
こんな感じだったのですが、既にこのバージョンは古くなって使えなくなっていました。
ならばと最新版でコンパイルするとコンパイルエラーが多発してうまくいきません。
GitHubのサンプルResolvingHostNames.inoを見ると

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include <MDNS_Generic.h>

のようなコメントもありましたが、依存関係を見るとWiFiを参照していたりと本来ネットワーク媒体には非依存で作成すべきなところがだいぶ複雑になっていそうです。
そこでもっと軽いライブラリはないかなと探してみたところ、やはりいました。

ArduinoMDNS


PlatformIOにもありましたので早速使うことにしました。
依存関係も無くすっきりとしたライブラリのようです。

今回のplatformio.iniは
[env:m5stack-atom]
platform = espressif32
board = m5stack-atom
framework = arduino
monitor_speed = 115200
lib_deps = 
	m5stack/M5Atom@^0.1.0
	arduino-libraries/Ethernet@^2.0.2
	arduino-libraries/ArduinoMDNS@^0.0.0
こんな感じです。

早速テストして見ると、パニックを起こしてしまいます。
どうやらアドレスエラーのようです・・・
前回同様またソースを見ることになるとは(( _ _ ))..zzzZZ

_finishedResolvingNameが原因でした


ソースを見るとどうやら_finishedResolvingNameメソッドでアドレス例外を出しているようです。
void MDNS::_finishedResolvingName(char* name, const byte ipAddr[4])
{   
   if (NULL != this->_nameFoundCallback) {
      if (NULL != name) {
         uint8_t* n = this->_findFirstDotFromRight((const uint8_t*)name);
         *(n-1) = '\0';
      }
      this->_nameFoundCallback((const char*)name, IPAddress(ipAddr));
   }

   my_free(this->_resolveNames[0]);
   this->_resolveNames[0] = NULL;
}

このメソッドは名前解決が出来た時に呼び出されてコールバック関数を呼び出すのですが、ソースを検索すると、名前解決できなかった時も呼び出されているます。但しipAddrがNULLで呼び出されていました!(前回調査時と同じ不具合)ということでその部分を以下のように変更して問題は解決しました。
this->_nameFoundCallback((const char*)name, 
                 (ipAddr == NULL ? INADDR_NONE : IPAddress(ipAddr)));

resolveNameサンプル


ヘッダファイル:
    DNSClient dns;
    EthernetUDP udp;
    MDNS mdns = MDNS(udp);
ソースファイル:
/* ****************************************************************************
 *      DNS
 ******************************************************************************/
IPAddress resolved_ip_address;
void nameFound(const char* name, IPAddress ip) {
    resolved_ip_address = ip;
    Serial.println(ip == INADDR_NONE ? " failed !!!" : " successed !");
}

IPAddress NetworkClientW5500Class::resolveName(const char *name) {
    IPAddress ipAddress;
    boolean rc = ipAddress.fromString(name);
    if(!rc) { // IP指定だった場合は名前解決不要
        if(this->useDNS) {
            int ret = this->dns.getHostByName(name, ipAddress);
            if (ret != 1) {
                // mDNS初期化
                if(!this->beginMDNS) {
                    if (!this->mdns.begin(Ethernet.localIP(), this->client_name)) {
                        // mDNS初期化エラー
                        Serial.println("Error setting up MDNS(W5500) responder!!!");
                        while(true) { 
                            delay(1000);
                            Serial.print(".");
                        }
                    }
                    this->beginMDNS = true;
                    this->mdns.setNameResolvedCallback(nameFound);
                    Serial.println("mdns.begin is success !");
                }
                Serial.print("host(");
                Serial.print(name);
                Serial.print(") IP address resolving ");
                int count = 0;
                resolved_ip_address = INADDR_NONE;
                while(true) {
                    if (!this->mdns.isResolvingName()) {
                        this->mdns.resolveName(name, 5000);
                        count++;
                        if(count > DNS_RETRY_COUNT)
                            break;
                        else if(count > 1)
                            Serial.print("retry resolving ");
                    }
                    Serial.print(".");
                    this->mdns.run();
                    if(resolved_ip_address != INADDR_NONE) {
                        ipAddress = resolved_ip_address;
                        count = 0;
                        break;
                    }
                    delay(100);
                }
                if(count > 0) {
                    // 名前解決できず
                    Serial.println(" was ended in failure!!!");
                    while(true) { 
                        delay(1000);
                        Serial.print(".");
                    }
                }
            }
            Serial.print("host(");
            Serial.print(name);
            Serial.print(") IP address : ");
            Serial.println(ipAddress);
        } else {
            Serial.print("host(");
            Serial.print(name);
            Serial.print(") name resolution failed !!!");
            while(true) {     
                delay(1000);
                Serial.print(".");
            }
        }     
    }
    return ipAddress;
}

2022年5月24日火曜日

bullseyeで初期設定後画面が真っ黒になって困った

あれ、画面が真っ黒に 

Raspberry Pi OSとして最近はbullseyeを主に使っています。
今まではIoT用途が多かったのでヘッドレスでのセットアップがばかりでしたが久々にディスプレイ+キーボード+マウスの構成でインストールをしたところ初期設定後の再起動で画面が真っ黒になって困ってしまいました。

どうやら言語設定を日本語にすると画面が真っ黒になってしまうようです。

最新のImagerでは色々と初期設定が可能ですが何もしないで今まで通りのインストールを行うと英語の初期設定画面は問題なく表示されるのですが、ロケールなどを日本語環境用に設定した後のリブート後に画面が真っ黒になってしまいます。

OSは問題なく起動されているのでsshでログインすることは可能です。

インストール環境

Raspberry Pi 4B 8MB
MicroSDカード:GIGASTONE 32MB
Raspberry OS:2022-04-04-raspios-bullseye-arm64.img
ディスプレイ:I-O DATA EX-LD2071TB
キーボード、マウス:自宅にあったもの

boot.txtの修正で問題解決

他のディスプレイに接続すると問題なく画面が表示されるディスプレイもあります。
どうやらディスプレイとの相性のようです。

昔もディスプレイとの相性があってconfig.txtをいじったことを思い出しました。

と言うことで今回はSDカードを取り出してWindowsで/boot/config.txtの以下の部分を修正して問題なく画面が表示されるようになりました。
値についてはそれぞれの環境によって違いますが参考としてはこちらと各自のディスプレイの取説を見て下さい。

ちなみにI-O DATA EX-LD2071TBは1920×1080のプログレッシブモードでHDMI接続なので1080pの60Hzの設定(hdmi_mode=5)を使用しました。

framebuffer_width=1920
framebuffer_height=1080

hdmi_group=1
hdmi_mode=5


EXCELの表をKaTeX形式に変換するマクロ

生成AI時代にプログラミング言語を学習する必要はあるのか? 最近では生成AIがプログラムを作成する時代になってきましたが、そんな時代にプログラミング言語を学習する必要はあるのでしょうか? ということで早速 Google さんに聞いてみました。 生成AI時代にプログラミング言語を学...