あなたの関数の色は何色ですか?(2015)

2026/05/27 0:58

あなたの関数の色は何色ですか?(2015)

RSS: https://news.ycombinator.com/rss

要約

日本語訳:

元の要約は、すべての主要な要点を効果的に伝えています。改善の余地はなく、忠実かつ明瞭で簡潔です:

まとめ:

JavaScript 開発は、同期コードと非同期コードの間における根本的な二分割により、開発者に大きな苦痛をもたらしています。この複雑さは、厳格な色分けルールが冗長な構文を強制し、痛みを伴う依存関係を生成するという架空の言語を通じて示されており、これは「コールバック地獄」から Promise へ JavaScript が進化した経歴を反映しています。Promise を用い더라도、値を直接利用するために待機(await)を行わない限り直接使用できないため、クリーンな非同期ロジックを書くには特別なラッパーが必要となることが多くあります。一方、C# の

async-await
メカニズムは、式のネスティングを可能にし、基盤にある複雑さを隠蔽することで、標準的な関数のように値を直接使用することを可能にします。また、Go、Lua、Ruby などの他の言語では、同期および非同期の操作を区別しない真の並行性をモデルとしたアプローチにより優れた結果が得られています。Java もまた、コードをこの 2 つの要素に分けることを避けています。この分離は現在、困難なエラー処理を通じて生産性を低下させ、同期表現内の非同期ロジックを組み込むのに容易さを制限しています。統合された並行性モデルへの移行は、API デザインの単純化をもたらすだけでなく、維持可能なアーキテクチャで企業が苦闘している样板コードを大幅に削減することが可能です。

本文

プログラミングにおける「赤と青」の罠:非同期処理の苦しみを告発する記事の日本語化と整理

序論:古風な言語への愛とリスク

  • 古風なプログラミング言語への熱狂が最も心を奮い立たせます。
  • 「ブルーブル(Blub)」批判のような大衆向け言語への辛辣な言及は、スタックオーバーフローへの畏敬と交わりつつあります。
  • Chisel-sharp ツールという開化的な言語こそが、熟練の職人のためのものですが、激しい評論にはリスクが伴います。
  • 皮肉を浴せた言語が読者の好物である場合、群衆による怒りや暴徒化(ピッチフォークと火把)を招く可能性があり、**刎首(すわぎ)**となる懸念があります。

新しい言語:A-NEW-LANGUAGE

ブログ記事のための新しい言語は、既存の JavaScript 的な文法(中かっこ、セミコロン、

if
while
など)を採用し、以下の機能を備えます。

基本的な構文と機能

function thisIsAFunction() {
  return "It's awesome";
}
  • ファーストクラス関数をサポートしています。

  • **高階関数(Higher-order functions)**を採用し、例として

    filter
    関数を定義します。

    // collection の predicate に一致する要素をすべて含むリストを返す
    function filter(collection, predicate) {
      var result = [];
      for (var i = 0; i < collection.length; i++) {
        if (predicate(collection[i])) result.push(collection[i]);
      }
      return result;
    }
    
  • テストフレームワークデータパースでも同様に活用されます。

    describe("An apple", function() {
      it("ain't no orange", function() {
        expect("Apple").not.toBe("Orange");
      });
    });
    
    tokens.match(Token.LEFT_BRACKET, function(token) {
      // リテラルリストをパース...
      tokens.consume(Token.RIGHT_BRACKET);
    });
    
  • 関数の受け渡しと再利用はFunctapaloozaと呼ばれるほど素晴らしいものです。


あなたの関数はどの色ですか?(WHAT-COLOR-IS-YOUR-FUNCTION)

しかし、この言語には狂気のような特徴があります:すべての関数には色が付けられています。赤か青かの二択です。

基本ルール

  1. 色の指定:単一の
    function
    キーワードではなく、以下のどちらかを選択します。
    blue_function doSomethingAzure() {
      // 青い関数...
    }
    
    red_function doSomethingCarnelian() {
      // 赤い関数...
    }
    
  2. 呼び出し方:関数の色に応じた構文が必要です。
    doSomethingAzure()blue;   // 青い関数の呼び出し
    doSomethingCarnelian()red; // 赤い関数の呼び出し
    

追加の制約とリスク

  • 色ミスの結果:色の組み合わせを間違えると、悪夢のようなエラーが発生します(例:赤い関数を

    blue
    で呼ぶ)。

  • 相互呼び出しの制限

    • ✅ 赤い関数の中に青い関数を呼ぶことは可能です。
      red_function doSomethingCarnelian() {
        doSomethingAzure()blue;
      }
      
    • 逆は不可。青い関数の中に赤い関数を呼ぶと「ナイト・クラウン」スパイダーマウス級の恐怖が訪れます。
      blue_function doSomethingAzure() {
        doSomethingCarnelian()red; // 禁止!
      }
      
  • 高階関数の困難さ

    filter()
    などの高階関数を定義する際に、色の選定が難しくなります。

    • 解決策として
      filter()
      を赤く設定し、双方を受け入れることができますが、新たな制約が生じます。
  • 赤い関数のコスト

    • 呼び出すたびに**痛み(面倒なループや文脈の制限)**を伴います。
    • API を利用する全員が「唾を吐きかけ」るほどの不快感を引き起こします。
  • コアライブラリの問題:組み込みのコア関数の一部が赤(非同期)であるため、回避できません。


問題の正体は関数型プログラミングの方です!(ITS-FUNCTIONAL-PROGRAMMINGS-FAULT)

この「色の制約」の本質的な原因は、高階関数再利用可能な関数の必要性にあります。

  • 高階関数の多様性問題
    • 関数の色に対する多態性が必要であり、理屈に苦しむ必要があります。
    • グラフ上のソーシャルネットワーク(ダイクストラのアルゴリズムなど)を独立した関数として再利用する際、呼び出し元の色の統一が困難です。
  • 開発の阻害要因
    • 常に「色」について考える必要があり、それは開発における砂のように邪魔な存在となります。

色彩豊かな寓話(A-COLORFUL-ALLEGORY)

この「色」という寓話は、文学的なトリックであり、実際には人種差別非同期処理の苦しみを表しています。

赤い関数とは何か? 赤い関数は非同期(asynchronous)なものです。

Node.js で JavaScript を書く場合、コールバックを伴う関数はすべて「赤い関数」です。前述のルールは以下の非同期処理の特性に完全に対応しています。

非同期関数の特性(=赤い関数の特性)

  • 返値の違い:値を返しず、代わりにコールバックを呼び出します。
  • 結果の与え方
    return
    ではなく、渡されたコールバックを通じて結果を与えます。
  • 相互呼出し禁止:同期関数から直接非同期関数(赤)を呼ぶとエラーになります(結果が確定していないため)。
  • 制御フローの制限:式内の構成にできず、
    try/catch
    や多くの制御フロー文法と併用できません。
  • コアライブラリの性質:Node の標準機能はすべて非同期です(※最近は
    ___Sync()
    版も出てきました)。
  • コールバック地獄:面倒な構造が「赤い関数」の存在そのものによって発生します。

私は未来の方が良くなることを約束します(I-PROMISE-THE-FUTURE-IS-BETTER)

コミュニティはこれらの問題を解決するために「プロミス(Promises)」や「フューチャー(Futures)」を導入しました。

  • プロミスの役割:崩れたコールバックとエラーハンドラをラップした、非同期操作を表すファーストクラスオブジェクトです。
  • 限界
    • 規則 #4(呼び出しの痛み)は緩和されますが、根本的な制約は残っています。
    • 例外処理や制御フロー文法との併用は依然として困難です。
    • 同期的コードからプロミス/フューチャーを返すことも不可能(またはメンテナンスの悪化を招きます)。

結論:

  • プロミス/フューチャーを導入しても、言語は非同期と同期の二分割のままであり、開発者の不幸は続きます。
  • 現状では、顔立ちは「刎首」そのものです。

私は解決策を待ち望んでいます(IM-AWAITING-A-SOLUTION)

C# は

async-await
キーワードを導入し、非同期処理を同期的ように書けるようになりました。Dart もこれを採用しました。

Async-Await の効果

  • 同期的な書き方で非同期呼び出しが可能になり、例外処理や制御フローにも埋め込みやすくなりました。
  • 規則 #4 の解決:赤い関数を呼ぶ際の「痛み」を軽減しました。

しかし残る問題点

  • 二つの色は依然として存在します
    • 同期関数(値を返す)
    • 非同期関数(
      Task<T>
      Future<T>
      を返す)
  • 呼出し方の変化
    • 同期関数:単に呼び出す。
    • 非同期関数:
      await
      が必要。
    • 結果を受け取るためには、ラッパーオブジェクトを「解凍(await)」する必要があります。

根本的な解決に至らない理由

  • Async-await
    はコンパイラが CPS(継続パススタイル)変換を行うのを助けますが、完全な解消ではありません
  • コードベース全体に「色」による概念が滲み込みます。高階関数や再利用を試みる限り、この問題は再発します。

どの言語は色がありませんか?(WHAT-LANGUAGE-ISNT-COLORED)

JS, Dart, C#, Python および CoffeeScript など、非同期 IO を持つ多くの言語はこの「色の問題」を抱えています。 一方、Javaは非同期処理に慎重に進化しており、Go, Lua, Ruby などは根本的に問題がありません。

共通点は何か?スレッド(Thread)

  • 切り替え可能な複数の独立したコールスタックです。
  • OS スレッドでなくても良い場合:
    • Go: ゴルーチン (Goroutines)
    • Lua: コルーチン (Coroutines)
    • Ruby: ファイバー (Fibers)

これらのアーキテクチャにより、IO 待機時でも他の処理を継続でき、「同期」と「非同期」の境界線がなくなります。C# はスレッドを活用することで非同期の痛みを回避しています。


過去の操作への回顧(REMEMBRANCE-OF-OPERATIONS-PAST)

根本的な問題は**「操作完了後の位置情報をどう引き継ぐか」**にあります。

  1. 通常のプロセス
    • コールスタックに現在地を保持し、関数呼び出しを追跡します。
    • 非同期 IO を実行すると、OS レベルでの待機が必要になり、コールスタック全体がアンワインド(破棄)されます。
  2. 解決策としての CPS
    • Node.js はクロージャを使ってすべてのコンテキストを保存し、結果を渡す仕組みを作りました。
    • これを**継続パススタイル(CPS)**と呼びます。
    • コードが複雑化し、人間が手動でクロージャを具体化する必要があります。

プロミスやフューチャーも同じ問題

  • これらは巨大な関数リテラルの山を手作業で作成する必要があるため、根本的な解決になっていません。

生成された解決策を待っています(AWAITING-A-GENERATED-SOLUTION)

Async-await
はコンパイラが CPS 変換を行うために
await
を挿入点として利用しますが、完全な解放ではありません。

  • ジェネレータとの類似
    • yield
      キーワードを持つジェネレータは、同様の手法でゲームループなどを実装できます。
    • しかし、結局のところ関数にはヒープ上の一連のクロージャが塗られています。
  • スタックアンワインドの必須性
    • どのアプローチであっても、非同期処理完了時にはコールスタックを再構築する必要があります。
    • これが「赤い関数は赤い関数のみから呼べる」という制約の正体です。

具現化されたコールスタック(REIFIED-CALLSTACKS)

解決策は明確です:**スレッド(グリーンまたは OS レベル)**を使用することです。

  • Go のアプローチ
    • IO 操作で待機しても、そのスレッド全体を停止せず、他のタスクに切り替えます。
    • 「同期」と「非同期」の区別自体が存在しません。
    • このため、前述の 5 つの規則による痛みは完全に消えます

結論

  • 新しい熱い言語や非同期 API を紹介された時、再び「赤い関数」と「青い関数」の話になるのを避けるために:スレッドベースのアプローチを選ぶべきです。

同じ日のほかのニュース

一覧に戻る →

2026/05/26 5:41

いくつかの興味深い現代風ピクセルフォント

## Japanese Translation: Vercel による Geist Pixel は、新しさ重視のベクトルフォントから、プロフェッショナルな生産環境に適合した堅牢で機能的なタイポグラフィシステムへの転換を象徴する。アンドリュー・グリーソン氏の Analog Mono(低基準線問題を解決)、ジョセフ・ファチュラ氏の Two Slice(読みやすい 2 ピクセル高のベクトルフォント)、および古谷由美氏の Coral Pixels(ノスタルジックなサブピクセルレンダリングによるフレアを包含)など、過去のデザインは特定の美的特徴や歴史的真似に焦点を合わせていたのに対し、Geist Pixel は重要な生産上の課題に取り組む。ビューポート間での一貫したスケーリングを保証し、対立するタイポグラフィ指標を解決するとともに、文字形式以外の領域(キアニング、メタデータ、追加のグリフ、垂直指標など)において「目に見えない本業」として多大な努力を投入している。ユーザー体験を劣化させる可能性のあるリスクの高い新奇品ではなく、Geist Pixel は広範なタイポグラフィエコシステムにおける信頼性の高いシステムツールおよび拡張機能として振る舞う。この進化は、現代的インターフェースに必要な本質的なタイポグラフィ的堅牢性を保ちながら、画面上で本物らしいテクスチャを維持することを可能にする新たな業界標準を確立する。 ## Text to translate: Improved summary: Geist Pixel by Vercel marks a shift from novelty vector fonts to a rigorous, functional typography system built for professional production. Unlike earlier designs—such as Andrew Gleeson’s Analog Mono (fixing low baseline issues), Joseph Fatula’s Two Slice (a 2‑pixel tall readable vector font), and Kumiko Yoshida’s Coral Pixels (incorporating nostalgic subpixel rendering fringing)—which focus on specific aesthetic quirks or historical replication, Geist Pixel addresses critical production challenges. It ensures consistent scaling across viewports, resolves conflicting typographic metrics, and includes significant “invisible hard work” beyond letterforms in areas like kerning, metadata, extra glyphs, and vertical metrics. Rather than being a risky novelty that can degrade user experience, Geist Pixel acts as a reliable system tool and extension within a broader typographic ecosystem. This evolution establishes a new industry standard where pixel fonts maintain authentic visual texture while preserving the essential typographic rigor required for modern interfaces.

2026/05/23 2:17

Adobe と Microsoft を飛び越えてGitで管理する書籍製作パイプラインを作成しました

## 日本語訳: 著者は、新規の形式付けをソフトウェア工学上のタスクとして扱い、Adobe InDesign などの高価なライセンスに依存する脆弱な専用ファイルから、オープンでプレーンテキスト形式のアートファクトへの移行を行うことで、自己出版の自動化を目指している。以前は Microsoft Word と Adobe InDesign を用いて印刷物を制作しており、Calibre を使って Kindle 版への変換を試みても品質が不足していた上、LibreOffice のアップデートにもかかわらず高品質なタイポグラフィを達成できていなかった。今回の移行では LaTeX と自作の Python スクリプトを採用し、電子書籍版および印刷版双方で高品質なテキストを提供すると同時に、Adobe InDesign などの高額ライセンスへの依存度を低減させている。 最も重要な点として、Standard Ebooks のガイドラインを採用することで、厳格なスタイルマニュアルとコマンドラインツールが不可欠な「リンター」として機能し、コードの品質を自動的に検証してデジタル上のエラーを未然に防ぐ。最終出版である『サルデーニャ公(Prince of Savoy)』により、Git を用いたバージョン管理に基づく開発へのピボットが完了した。今後、プロジェクトでは汎用的なスクリプトを活用し、Open Document XML をそのままクリーンな XHTML と LaTeX にマッピングする手法を採用する。この方法は、著者にとって持続可能で再現可能なアプローチを提供し、脆弱なバイナリ形式を意味論的データ構造に置き換えることで、高価なソフトウェアへの依存関係を持たずに長期的な互換性を促進する。

2026/05/26 14:57

予兆的な再会

## Japanese Translation: 学術的な集会で、著者は同世代の多くが大型言語モデル(LLM)による知識労働の人間的側面の喪失に対して広く不安を抱いているのに対し、以前の高齢世代が直面した恐怖とは対照的だと指摘した。この感情は、ウェスリアン大学の工学プロジェクトのために構築され、後にブラウン大学 CS の卒業生アダム・レビエンタールによってメンテナンスされた 1992 年のネットワーク接続型テトリス「BattleTris」の復活という具体的な成功と鮮明な対比を形成していた。長年にわたり、グリッド構成を変更する特定の武器を含むこのレガシーコードベースは、元の 32 ビット Solaris ビルドに影響を与えたことのない現代システム上でクラッシュに見舞われていた。最近、「スパイ」兵器によって開始された試合では、バッファ過負荷によりスタックのスマッushing の検出エラーが発生した:`sendBoard` 関数は 4 バイト(`sizeof(int)`)しか割り当てていないが、8 バイト(`sizeof(unsigned long)`)を書き込み、結果として現代の 64 ビット Linux システム上で 1114 バイトの過負荷を引き起こしていた。 多くの専門家の圈で現在恐れている LLM クロードを使用することで、チームは割り当てと書き込み操作間のこの特定の不一致を特定した。これらの AI の洞察に基づいたターゲットされた修正を適用することで、彼らはゲームを成功裏に移植し再構築し、20 年間クラッシュせずにもう一度元の著者たちにプレイさせることができた。この成功は、LLM が歴史的なデジタルアーティファクトの保存において脅威ではなく有益なパートナーであることを示す強力な証拠であり、現在の不安を引き起こすその技術自体が、複雑なレガシーシステムのデバッグを効果的に支援し、古いプロジェクトの継続的な関連性を確保することを可能にすることを明らかにしている。