Rust から来た場合の Zig の感じ方

2026/09/19 22:55

Rust から来た場合の Zig の感じ方

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

要約

Japanese Translation:

7 年間 Rust を開発してきた著者が最近、

jsonpath-rust
ライブラリを Zig に移植し、両言語の哲学間の明確なトレードオフを浮き彫りにしました。Zig は優れた速度と、メモリ割り当てを手動で制御したい人々が好む命令型スタイルを提供していますが、現在では Rust の成熟したエコシステムと比較すると未熟な印象を与えます。この移行には大きな構造的変更が必要であり、深い階層のフォルダ構造と統合された IDE(RustRover など)から、フラットなファイル構造と
helix
alacritty
zellij
などのツールの使用によるコマンドライン環境への移行を余儀なくされました。
build.zig
を通じたビルド管理は簡素化されていますが、テスト実行の摩擦により、冗長なインライン定義を使用するのではなく
build.zig
に明示的なテストを設定しました。重要な点は、Zig が Rust の自動メモリ安全性機能や関数型イディオム(例えばモノイド)を欠いていることです。その結果、開発者は各関数レベルで手動の割り当て管理(
init
/
deinit
)を行うなど、冗長なコードを書くことを強いられいます。Zig は現代的な設計によって C を凌ぐ可能性を秘めていますが、現在では生活の質的な機能と成熟したライブラリにおいて苦戦しており、例えば標準ライブラリの API は頻繁に変更され、現在の正規表現実装は堅牢なユニコード属性エスケープをサポートしていません。結局のところ、低レベルのパフォーマンスタスクには理想的ですが、自動的安全保証、広範なエコシステム、関数型パラダイムを優先するチームにとって、本番アプリケーションにおいては Rust の方が実用的である可能性があります。

本文

Rust と Zig での JSONPath 実装比較:直感と代償の物語

はじめに

過去 7 年間、主にオープンソースプロジェクトで Rust 開発に従事し、言語とそのエコシステムへの堅実な感覚を養ってきました。私は Rust の関数型側面(純粋な関数、豊かなタイプなど)に惹かれていますが、同時に他の言語への好奇心も衰えません。特に Zig は、低級処理と軽量性を兼ね備えつつ、注目の C 語の後継候補として確かな地位を築いています。

キャリア早期に C 言語との経験があるため、この比較は非常に興味深かったのですが、当稿における Zig の体験は今回のプロジェクトから始まったものです。したがって、以下の観察結果は:

  • 日常的に Zig を扱っている方々には一見幼稚で当然のものに見える可能性があります。
  • 途中で下した判断が必ずしも最適ではなかったかもしれません。

それらは深い Zig 慣習というよりは、Rust から持ち越された習慣によって形作られたものです。それでも構いません。誰もがどこかから出発せねばならないからです。

公平な比較のため、すでに Rust で実装したものを Zig でも再実装することを決定しました。遊び心だけの試作ではなく、かつ膨大なプロジェクトでもない、実際にコミュニティが利用可能な「何か」を目指しました。その題材は RFC 9535 で規定された JSON クエリ言語「JSONPath

jsonpath-rust
)です。

IDE のサポート:CLI への回帰

まず驚いたのは IDE サポートのほぼ全然的欠如でした。Rust では IntelliJ Platform ベースの RustRover などを使用できますが、Zig では構文強調表示や基本的な自動補完しか提供されていませんでした。

  • これが予想できたことかもしれませんが、私を「コマンドライン上で主に扱う」という基礎に戻しました。
  • 最初は欠点のように思えたものが、体験の中で最も興味深い部分の一つになりました。
  • 実は、純粋な CLI ツールに依存することはそれほど単純でなかったという事実を忘れていただけだったのです。

build.zig
による容易な課題解決

得られた最初の教訓は、

build.zig
でこの課題が驚くほど容易に解決することです。

最終的に決定した構成:

# すべてのテストを実行
zig build test 

# 特定のテスト(例:"basic")のみを実行
zig build test -Dfilter="filter match function basic" 

# デバッグモードですべてのテストを実行
zig build test -Ddebug-query=true 

# コンプライアンススイートを実行
zig build compliance

# ユニットテスト+コンプライアンスチェック
zig build check 

この前提を受け入れると、作業は非常に Refreshing になりました。Zig のおかげで大きな連鎖反応が始まり、完全に IDE に依存する環境から Helix(エディタ)+Alacritty(ターミナルエミュレータ)+Zellij(マルチパネート muxer)という構成へ移行できました。

平坦な構造:拡張性と直感のトレードオフ

Rust や多くの言語では、ファイルサイズとフォルダの階層深度のバランスを取るのに多大な時間を費やしてきました。しかし Zig はこれを積極的に奨励していない(C と同様です)。

  • ネストのリスク: ファイルとフォルダをネストさせるとインポートの摩擦が生じます。「その分際ってどうするのか?」という問いが浮上します。
  • 大文件の利点: 関連するものを一つの大文件にまとめ、セクションごとにスライシングすると、ナビゲーションや実質的な利点が大きいです。

基本的に Zig は平坦な構造を促します。モデルが必要なら隣に

model_<companion>
を作成するだけで十分です。

  • 大規模プロジェクトへの拡張性: 初期には拡張性がなさそうに見えますが、真の階層が必要になる閾値は予想よりも高いことが分かりました。
  • 習慣と必要性: プロジェクトを整理するのは本当に必要か、単なる習慣かを再考させられます。一日目からフォルダに手を伸ばすことのできない規模感は、実際のそれより小さい可能性があります。

構造化の違い:並置比較

Rust (

src/
): 多くの階層とファイルに分岐します(例:
parser/
,
query/
など)。

src/
├── lib.rs
├── parser.rs
├── parser/
│   ├── errors.rs
│   ├── macros.rs
│   ├── model.rs
│   ├── tests.rs
│   └── grammar/
│       └── json_path_9535.pest
├── query.rs
└── query/
    ├── atom.rs
    ├── comparable.rs
    ├── comparison.rs
    ├── filter.rs
    ├── jp_query.rs
    ├── queryable.rs
    ├── segment.rs
    ├── selector.rs
    ├── state.rs
    ├── test.rs
    └── test_function.rs

Zig (

src/
): 極めて平坦で簡潔です。

src/
├── root.zig
├── parser.zig
├── model.zig
├── model_query.zig
└── query.zig

テスト機能:冗長性の回避

RFC 9535 のコンプライアンススイートを一旦 aside に置き、言語そのものに焦点を当てます。

  • Rust: インラインユニットテストがデフォルト。統合テストは独立したフォルダで例外扱い。
  • Zig: 平坦な構造のため、個別のテストファイルを作るか、インラインさせるかの 2 つの選択肢に迫られます。どちらも clutter になりがちです。

私は後者の選択肢(テストを直接モデルファイル内にインライン)を選びました。

  • build.zig
    で明示的に構成する必要がありましたが、一度セットアップできれば良好に機能しました。
  • 総括: テストの作成・管理は Rust に比べて容易ですが、Zig の場合は言語固有の手動メモリアロケーション制度による摩擦が大きいです。

関数型パラダイムの欠如:設計思想の違い

Rust は命令型言語ですが、機能的概念(ゼロコストイテレータ、ADT、パターンマッチング、モノイド型等)を大いに採用しています。対照的に Zig はインプレイスな変異と命令的な世界へと追いやられます。

両者が近づく点:和型(Sum types)

Rust: 純粋で直接的なトレイト実装。 Zig: Duck-typed な実装(関数が存在するかを確認するだけ)。

再帰も双方で機能しますが、言語はすぐに機能スタイルから逸脱させるよう強制します。特に直接アロケーターと付き合うことが主な要因です。

具体例:Reduce vs. Fork / コビネーター vs. ループ

特徴Rust (コビネーター/イテレータ)Zig (ループ/状態管理)
アプローチ
iter().map(...).reduce(...)

新しい構造を構築するが、メモリコストが高い。
直接アロケーターを扱います。
fork()
で状態のコピーを作成。
例:Reduce
selectors.iter().map(...).reduce(...)
lhs_branch = try iter.fork();

その後
deinit
して破棄。
例:コビネーター
enumerate().filter().map().collect()
while
ループでインデックスを管理。
remove()
でリストを直接変異。
  • 結論: これは各言語の設計目標と対象ドメインを反映しており、妥当なトレードオフです。しかし主観的に、Zig コードは Rust の counterpart よりも読みづらいと感じました。

不変モノイド vs. 変異:核心の違い

Rust では単純なモノイド変換を行い、新しいデータ構造を返します。一方 Zig はインプレイスでのオーバーライトへ切り替わります。

  • Rust:
    Data::Ref
    から
    Data::Refs
    に移動させ、新しい
    Data
    を返す。
  • Zig: リストを直接変異させます (
    iteration.remove(i)
    など)。

メモリ破損:構造体内への移動が失敗するとオランピングアロケーションが発生する

// 以下はバグ示例です
pub fn appendBuggy(self: *Iter, v: *Value, path: []const u8) !void {
    const duped = try self.allocator.dupe(u8, path);
    // BUG: errdefer がいない -> アロケーション失敗時に duped を解放しない
    try self.cursors.append(self.allocator, .{ .json = v, .path = duped });
}
  • 検出:
    FailingAllocator
    でテストすると、配列の拡張(第 2 のアロケーション)が失敗し、最初の文字列(第 1 のアロケーション)をオランピングします。
  • 修正:
    const duped = try self.allocator.dupe(u8, path);
    errdefer self.allocator.free(duped); // アロケートしたが連結失敗時の処理
    try self.cursors.append(self.allocator, .{ .json = v, .path = duped });
    

Rust での比較:コンパイル不可能なバグ

Rust では

Vec::push(item)
が item を移動させるため、成功か OOM で中止するかです。標準 API に「アロケートしたが連結されていない」値を手渡す失敗する push は存在しません。
errdefer
のギャップは最初から存在しないのです。

アロケーター:管理コストとテストツール

アロケーターはほぼすべての関数の引数にあり、各構造体もそれを保持します。

  • 明示的であるが tedious:
    init
    /
    deinit
    の慣習を慎重に守る必要があり、コールスタックが長い瞬間から規律が揺らぎ始めます。
  • TestAllocator の活用:
    TestAllocator
    が自動的にリークを検出してくれますが、失敗パスを実行するテストケースを書く必要があります。
  • : コードが複雑になるにつれて、バグは絡み合い隠れてしまいます(例:
    defer
    の順序付けミスによる二重解放)。

メモリリークの典型パターンと対策

  1. deinit の忘れ:
    MemoryLeakDetected
    で検出。
    defer iter.deinit()
    を追加。
  2. エラーパスでの deinit スキップ: エラー発生時に所有者が適切に解放されず、リーク。
    errdefer iter.deinit()
    で解決。
  3. 二重呼び出し:
    cache.append(result)
    後に
    result.deinit()
    を呼び出すと、キャッシュ内のポインタを指すメモリーを解放してしまう。「値を所有するのは一層のみ」という原則を守り、移動(ownership transfer)のタイミングで
    defer
    を外します。

ライブラリとコア API:若いエコシステム

Zig のエコシステムはまだ非常に若いです。

  • ライブラリの不足: 正規表現さえも完全に成熟しておらず、RFC 9535 のフィルター関数実装中にギャップとして浮上しました(例:
    mvzr
    は Unicode プロパティエスケープをサポートしていない)。
  • API の変化: 標準ライブラリ自体がバージョンごとに API を変更することがあり、導入時点で予想されていたことですが記録として注記します。

全体的な印象

この言語は Rust と異なりますが(誰がこう思ったでしょう、そうですよね)、本当に良い印象を残しました

  • シンプルでモダン: 爆速です。
  • C の真の後継者になるポテンシャル: 確信しています。

しかし、まだ若いことが示されており:

  • 言語の形状自体の所々が未完成に見えます。
  • 成熟するにつれて、より多くのクールなクオリティ・オブ・ライフ機能や構文糖を拾い上げる可能性が高いと考えます。

私はエコシステムに継続して貢献したいと考えており、価値あるプロジェクトが見つかるたびに貢献いたします。

リンク

  • jsonpath-rust
  • zig-jsonpath
  • ZigRust

免責事項: この記事全体を通してのスタイリングとエラー処理は、AI の助けを借りて改善されました。

同じ日のほかのニュース

一覧に戻る →

2026/09/19 19:46

1 年前に RL を用いた非自己回帰型決定モデルを構築した

## Japanese Translation: 本テキストは、エンタープライズワークフローを悩ませてきた高遅延と幻覚(ハルシネーション)のリスクを排除することを目的として設計された画期的な完全にオープンソースの AI モデル「Laya」を紹介する。標準的な生成型大規模言語モデルがしばしば 500〜2,000 ミリ秒の遅延を経験するのに対し、Laya は単一の GPU で顕著な 32.8 ms の遅延を実現し(バッチ処理された質問の場合には 7.2 ms)、これを達成するためには形式自由なテキスト生成を完全に回避し、代わりに辞書からオプションを選択する「choice」命令、順序付けされた評価基準レベルを割り当てる「score」命令、および真理値論理によって有用でない出力を示す「noul」という 3 つの特定の決定プリミティブのみを通じて構造化データのみを出力することを行っている。この建築学的なシフトは、ルーティングやスパム検出などの重要なタスクに対して瞬時に数学的に校正された確率を確保し、100 言語以上をカバーしている。TypeSafe の「Jev」といったプロプライエタリ競合製品に優越するように開発された Laya は、企業がローカルで展開することを可能にし、API 手数料と運用コストを大幅に削減する。将来的な改良により、現在のトークン予算の制限を超えたより大きなオプションセットを処理することが予想され、英語専用モデルに見られる一般的な失敗がないグローバルかつマルチスキーマの意思決定のための堅牢なソリューションとなるだろう。

2026/09/19 18:20

生成 AI で作られたポスターがひどいものに終わる必要はありません。

## Japanese Translation: チャットGPT は、AI アートにしばしば関連づけられる反復的・一般的な外見を避け、独自で高品質なポスターデザインを容易に生成できます。初期の要求では標準的なテンプレートが生成される場合もありますが、具体的な指示を与えることで、文脈に応じたテキストオーバーレイ付きのバウハウス幾何学や日本のミニマリズムなど、多様な芸術スタイルを解き放つことができます。以前の批評において「すべての AI 画像は同一である」と主張されていた点とは対照的に、洗練されたプロンプティングは、鑑賞者が直ちに機械生成であると特定しにくい独自性のある視覚コンテンツの作成が可能であることを証明しています。さらに、Claude や Gemini などの他の高度なモデルも、編集可能なテキスト層を含む PDF や HTML ファイルといった実用的に使用可能な形式を出力し、デザイナーが必要なグラフィックアセットを素早く取得する際に実践的な利便性を提供します。これらの成功した結果を他者が再現できるようにするために、著者は様々なポスタースタイルを網羅した 100 の即座に使用できるプロンプトのカタログを編纂しました。このリソースにより、各新しいプロジェクトに対して複雑な手動指示を必要とせずに、多様な視覚コンテンツを迅速に生成できるようになります。結局のところ、効果的なプロンプティングは、AI を退屈なデフォルトの源から、実世界のデザイン基準を満たすプロフェッショナルでユニークなグラフィックを作成する強力なツールへと変革します。

2026/09/20 5:00

インターネット検閲を測定し、最大級のオープンデータセットに貢献しましょう。

## 日本語訳: オニー・プローブは、インターネット検閲に関する世界の最大のオープンデータセットの中核を成すものであり、主に異なる国でどの特定のウェブサイトやアプリがブロックされているかを検証することを目的として設計されています。该软件の核心には、WhatsApp、Facebook Messenger、Telegram などの主要プラットフォームが利用者のネットワーク上でアクセス可能であることを確認するテストが含まれています。さらに重要なのは、M-Lab と共同で作成された標準化された測定方法である NDT テストを活用して、一般インターネットの速度と安定性を評価することです。このツールは Linux および macOS で動作し、個人の利用者がデジタル自由の解決策(例えば回避アプリ)が実際にはローカルの制限に対して機能しているかどうかを検証する能力を付与します。個人の検証を超えて、オニー・プローブ は研究者や組織に、世界の検閲トレンドを追跡するための不可欠なデータを提供します。M-Lab と協力することで、オープンソースコミュニティ全体で一貫性のある信頼できるパフォーマンス指標が確保されています。