Biff.graph:Clojure のコードベースを探索可能なグラフとして構造化する

2026/07/08 1:48

Biff.graph:Clojure のコードベースを探索可能なグラフとして構造化する

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

要約

日本語訳:

最も大きな進歩は biff.graph です。これは、レゾルバー(resolver)と呼ばれる仕組みを用いて、データベースと派生データを単一のクエリ可能グラフに統合するための軽量ライブラリです。Pathom などの重い代替手段とは異なり、このツールはデータ形状を宣言することを簡素化し、生のデータベースソースと複雑な論理的変換の区別を効率的に隠蔽します。biff.graph は、Datomic pull に着想を得た EQL パターンの修正版サブセットの上に構築されており、開発者は背後にある取得メカニズムの詳細な知識を必要とせず、アプリケーションデータ構造を定義できるようになります。该系统は、キャッシュ機能、バリデーション、バッチ処理などの主要な機能をサポートしており、パフォーマンス向上のため、複雑なクエリ計画ステップは意図的に省略されています。レゾルバーは、入力形状(通常はプライマリーキー)から出力形状(すべての属性と必要な結合を含む)へデータを転換する独立したロジックの断片として機能します。これらのレゾルバーは単に

model/
ディレクトリ内で組織化でき、「グローバル」レゾルバーは、特定の入力クエリを必要とせずに、クリーンなタイトルの生成のような複雑なバックグラウンドタスクを処理します。このライブラリはキャッシュ用のミドルウェアとコンテキストラッパー(
new-ctx
)を通じて統合され、アクセス可能なレゾルバー関数によるテストに対応し、
biff.fx
マシンと共に実行可能ロジックフローを定義する作業も可能です。究極的には、biff.graph は独立したロジックの断片が変換を処理でき、重厚なアーキテクチャ上のオーバーヘッドや特定の入力クエリを必要としないことで、グラフ様構造に依存するアプリケーションの開発を簡素化します。

本文

biff.graph データ可視化ガイド

biff.graph
を利用することで、データベースおよびビジネスロジック/派生データを単一かつ拡張可能なグラフとして一元管理し、照会(クエリ)が可能になります。

  • データモデルのコードは小さな独立した単位(「リゾルバー」)に分割できるため、アプリケーション側では必要なデータの形状を宣言するだけで、取得方法を記述する必要がなくなります。
  • これにより、特にコードベースが大きくなるにつれて理解しやすく、テストも容易になります。

概要と特徴

biff.graph
は本質的に Pathom の軽量版です。Pathom の機能サブセットのみを実装しており、意図的に簡素化されています。

メリットとデメリット

  • メリット
    • コードベース全体が約 600 行(クエリ実行部は約 200 行)という軽量構造です。
    • デフォルトで Biff に含まれることがありますが、学習コストをかけずにコード構造上の利点を活かすことができます。
  • デメリット
    • Pathom よりも一部のクエリが効率的に実行されない可能性があります
    • クエリ計画(プランニング)のステップを持たない点が最大の違いです。

機能サポート

  • バッチリゾルバーをサポートしています。
  • キャッシング機能をサポートしています。

依存関係

Maven Central での依存追加例です。

com.biffweb/graph {:mvn/version "2.0.0-rc7"}

ステータス

本ライブラリは、他の Biff 2 ライブラリが全てリリースされるまで**ベータ版(RC)**の状態です。

  • 互換性:現時点では重大な不互換の変更を予定しておりません。

API リファレンス

  • 主要なパッケージ名:
    com.biffweb.graph

コンセプト

biff.graph
は、EQL / Datomic の
pull
パターンに基づき、データを定義する際に少し改良されたサブセットを採用しています。

リゾルバー (Resolver)

**「リゾルバー」**とは、入力および出力のクエリが関連付けられた関数のことです。

  • 入力のクエリ形状: データベースから取得すべきデータの鍵(ID など)を受け取ります。
  • 出力のクエリ形状: 計算された結果や関連データを含んだマップを返します。

複数のリゾルバーを定義した後、

biff.graph
のクエリエンジンはそれらを利用して、照会された任意の形状のデータを返します。


コード例

バナナグラフモデル

以下のスニペットでは:

  1. シミュレートされたリゾルバー(
    rss-feed
    post
    )を定義しています。
  2. 派生データ計算のリゾルバー(
    clean-post-title
    )を定義し、絵文字を除去したバージョンを返しています。
  3. どの属性がデータベース取得か、派生処理かが自動で区別されます。
(require '[com.biffweb.graph :as biff.graph :refer [defresolver]])
(require '[clojure.string :as str])

;; --- 1. RSS Feed リゾルバー ---
(defresolver rss-feed
  {:input  [:rss-feed/id]
   :output [:rss-feed/title]}
  [_ctx {:rss-feed/keys [id]}]
  (get {1 {:rss-feed/title "My Blog"}}
       id))

;; --- 2. ポストリゾルバー ---
(defresolver post
  {:input  [:post/id]
   :output [:post/title
            :post/url
            {:post/rss-feed [:rss-feed/id]}]}
  [_ctx {:post/keys [id]}]
  (get {2 {:post/url      "https://example.com/my-post"
           :post/title    "My Post 🎅"
           :post/rss-feed {:rss-feed/id 1}}
        3 {:post/title    "My Other Post 🎅"
           :post/rss-feed {:rss-feed/id 1}}}
       id))

;; --- 3. デリバリーフ(派生ロジック) ---
(defn remove-emojis [s]
  (str/replace s #"🎅" ""))

(defresolver clean-post-title
  {:input  [:post/title]
   :output [:post/clean-title]}
  [_ctx {:post/keys [title]}]
  {:post/clean-title (-> title
                         remove-emojis
                         str/trim)})

;; --- 4. コンテキスト作成とクエリ実行 ---
(def resolvers [rss-feed
                post
                clean-post-title])

(def ctx (biff.graph/new-ctx resolvers))

(biff.graph/query ctx
                  [{:post/id 2}
                   {:post/id 3}]
                  [:post/id
                   :post/clean-title
                   ;; オプションの属性は [:? ...] で示します
                   [:? :post/url]
                   ;; ジョイン属性はネストされたマップで示します
                   {:post/rss-feed [:rss-feed/title]}
                   ;; オプションのジョイン属性
                   {[:? :post/rss-feed] [:rss-feed/title]}
                   ])
;; =>
[{:post/id           2,
  :post/clean-title "My Post",
  :post/url         "https://example.com/my-post",
  :post/rss-feed    {:rss-feed/title "My Blog"}}
 {:post/id          3,
  :post/clean-title "My Other Post",
  :post/rss-feed    {:rss-feed/title "My Blog"}}]

使用方法

リゾルバーの定義

通常、データベーススキーマに基づいてリゾルバーを自動生成する機能が必要です(

com.biffweb.graph/resolver
を使用)。ガイドラインは以下の通りです:

  • 1 トピック 1 リゾルバー: テーブル/エンティティタイプ 1 つに対して 1 つのリゾルバーを用意します。
  • 入力クエリ: 主キーのみを含めるべきです(例:
    [:person/id]
    )。
  • 出力クエリ: 他のすべての列/属性を含めるべきです(例:
    [:person/age, :person/favorite-color, ...]
    )。
  • ジョインキー: 外部キー/参照属性に対して、ジョインキーおよびそのサブクエリとして当該エンティティの主キーを含めるべきです(例:
    [{:person/pet [:pet/id]}, ...]
    )。
  • バッチ処理: リゾルバーオプションに
    :batch true
    を含めます。これにより複数のエンティティを一括で取得できます。この設定を持つリゾルバーは、入力マップのベクトルを受け取り、同じ順序の出力マップのベクトルを返す必要があります。
  • 実装: リゾルバー関数は事実上
    SELECT *
    を実行し、ジョインキーを確認しながらネストされたマップとしてフォーマットする必要があります。

※公開されていない

biff.sqlite
ライブラリには SQLite 向けの機能が用意されています(未編集の AI コードによる注記)。

その後、任意のリゾルバーを

com.biffweb.graph/defresolver
で定義できます。ヘルパー関数からのロジックを gradually に移動させることも可能です。

コンテキストの作成

最後に、定義したリゾルバーを

com.biff.web.graph/new-ctx
に渡します。

  • クエリエンジンが使用する単純なインデックス処理が行われます。
  • リゾルバーは、キャッシングや検証などの処理を行うミドルウェアでラップされます。

クエリの実行

リゾルバー定義後、必要な場所(例:Ring リクエストハンドラー)からクエリを実行します。

(defn settings-page [{:keys [session] :as ctx}]
  (let [user (biff.graph/query ctx
                               {:user/id (:uid session)}
                               [:user/email
                                :user/display-name
                                :user/subscribed])]
    ...))

上記の例では、

com.biffweb.graph/new-ctx
の出力が入ってくる Ring リクエストにマージされるミドルウェアがあることを前提としています。

デバッグ

com.biffweb.graph/query
内部で発生した例外は、
:biff.graph/trace
キーを通じて以下を教えてくれます:

  • クエリエンジンがグラフ走査のどの位置にあったか。
  • 入力データを解決しようとしたのはどのリゾルバーか。
  • 失敗したパスに焦点を当てて最小再現例を作成できます。

テスト

リゾルバー関数は

:biff.graph/resolve-fn
キーの下に格納されます。

(defresolver my-resolver
  {:input [:user/id]
   :output [...]}
  [ctx input]
  ...)

(deftest test-my-resolver
  (is (= ((:biff.graph/resolve-fn my-resolver)
          {:biff.graph/input {:user/id 1}})
         ...)))

biff.fx との統合

biff.fx
を使用している場合、ハンドラーマップに
com.biffweb.graph/fx-handlers
をマージできます。これにより、
:biff.graph.fx/query
キー下でクエリが公開されます。

(require '[com.biffweb.fx :refer [defmachine]])

(defmachine do-something
  :start
  (fn [{:keys [session]}]
    {:user [:biff.graph.fx/query
            {:user/id (:uid session)}
            [:user/email
             ...]]
     :biff.fx/next :next})
  ...)

defresolver
も、リゾルバーの本体を
biff.fx
マシンの形式として定義する変形をサポートします。これにより、リゾルバー内部でデータベース照会や外部サービス呼び出しなどの副作用処理を行うことができます。

注意点:

defresolver
で定義された状態関数は、通常の
biff.fx
マシンとは異なり、1 つではなく **2 つのパラメータ(
ctx
input
)**を受け取ることに注意してください。


biff.core との統合

(com.biffweb.graph/module)
をモジュールに含んでいる場合:

  • 他のモジュール上に
    :biff.graph/resolvers
    ベクトルを備えたリゾルバーを配置できます。
  • アプリケーションスキーマを
    com.biffweb.core/register
    で登録した場合は、
    biff.graph
    がリゾルバー出力がそのスキーマに適合していることを保証
    します。

ヒントとベストプラクティス

  1. ファイル構成: リゾルバーを
    model/
    配下に配置し、各ネームスペースが
    :biff.graph/resolvers
    を設定した
    biff.core
    モジュールを公開します。
  2. UI コンポーネント: hiccup を返すリゾルバーを作成することも可能です(例:ボタンやモーダルなど)。これらを
    ui_components/
    配下に配置し、特定のデータモデル向けの再利用可能なコンポーネントとします。
    (defresolver ... {:com.example/my-component (fn [{:keys [href]}] [:div ...])})
    
  3. グローバルリゾルバー: インプットクエリを持たない「グローバル」リゾルバーもあります。
    • 特定の条件を満たす全ユーザーを照会したいバックグラウンドジョブ用。
    • ctx
      から明示的な ID が不要なセッションデータ返信用。
  4. 認証(パラムス): パラメータからエンティティ ID を受け取り、権限確認を行いジョインとして返すリゾルバーを作成します。
    :output [{:params/widget [:widget/id]}]
    
    • 無権限の場合:例外を投げるか、出力からエンティティを省略するかのいずれかを選択可能です(HTTP 4XX への転換方法を探求中)。

同じ日のほかのニュース

一覧に戻る →

2026/07/12 7:38

イロウによる分散AI計算のためのメッシュ LLM

## Japanese Translation: ## 概要: Mesh LLM は、既存の GPU およびメモリを何台ものマシンから集約し、中央サーバーを必要としない軽量なインフラストラクチャとして統合することで、チームが人工知能を利用する方法を根本的に変革します。これは、OpenAI 互換 API(デフォルトアドレス:`localhost:9337/v1`)としてこの統合されたコンピューティングリソースを公開し、組織が高価でブラックボックス化しているクラウドプロバイダーへの依存を排除しながら、モデルの更新、データルーティング、および下位のハードウェアに対する完全な制御を維持できるようにします。これによりコストを増加させることはありません。 アーキテクチャは、MCP、HTTP、インференスストリーム、およびメッシュイベントを通じて暴露されるマニフェストベースのプラグインシステムにより拡張可能であり、ノートパソコンサイズから 235B パラメータの巨人までをカバーする 40 以上のモデルをサポートします。235B パラメータなど的大規模な mixture-of-experts モデルについては、Mesh LLM は内部名称「Skippy」を持つ「Split mode」を採用しており、モデルレイヤーを順次ステージに分割し、ピアツーピアルーティングを用いて活性化を適度なマシンのパイプラインを通って流します。 ネットワーク管理は、iroh エンドポイントメッシュによって行われ、ここで各ノード(サーバーまたはクライアント)は公開鍵を使用して独自のアイデンティティとして機能し、中央コーディネーターの必要性はありません。接続は認証されており、iroh リレーによる NAT 通過可能な QUIC セッションが支援され、地域をまたいでヒールパンチ/リレーフォールバック機構が備わっています。プロトコルには、ゴシップ、ルーティング、HTTP 用の`mesh-llm/1`、所有者コントロールプレーンのための`mesh-llm-control/1`、低遅延に敏感な活性化輸送のための`skippy-stage/2`という 3 つの特別な QUIC ALPN が使用されます。メイン接続内では、すべてのトラフィックは先頭のバイトでデマルックスされた双方向の QUIC ストリームとなり、特定のタイプ(`GOSSIP`、`TUNNEL_HTTP`、`ROUTE_REQUEST`、`PEER_DOWN`、`PLUGIN_CHANNEL` など)に分類されます。 ソフトウェアは非常に軽量であり、インストールには約 18 MB を必要とします。公開メッシュへの参加やベンダーロックインのないプライベートデプロイメントの完全な構成が可能です。将来の計画には、iroh の Swift SDK で構築された専用モバイルアプリが含まれており、これは台頭しつつあるエージェント通信プロトコル(ACP)をサポートし、他のクライアントがメッシュにシームレスに接続できるようにします。セキュリティ、バージョン互換性、および信頼に関する判断は、カスタムゴシップレイヤーを介して内部で管理され、スケーリングやネットワーク構成に関わらず自律性を確保しています。

2026/07/12 6:58

ゼロから設計されたオープンソースの携帯型ゲーム機「RISCBoy」

## Japanese Translation: RISCBoy は、RISC-V 互換 CPU とラスタグラフィックスパイプラインを从头設計されたオープンソースの携帯用ゲームコンソールです。その主要な成果は、合成可能な Verilog 2005 で記述され、完全に検証されたプロセッサ設計であり、Lattice iCE40-HX8k(7680 ロジック要素を使用、LUT4 ベース)などの特定 FPGA ハードウェアをターゲットとしています。プロジェクトは RV32IMC インスピーションセットに厳密に従い、M モード制御レジスタ、例外処理、ベクトored 外部割り込み向けの準拠拡張機能といった本質的な機能を実装することで、アーキテクチャ準拠の他、riscv-formal サイスイツを使用して厳格な形式的検証も実施しています。完全なソースコードは `git clone --recursive https://github.com/Wren6991/RISCBoy.git` で入手可能で、サブモジュールが必要な場合は手動での更新が必要です。開発には RV32IMC ツールチェーン(`./configure --with-arch=rv32imc` で構築)と Xilinx ISIM 14.x(Linux 専用)によるシミュレーション、そして `scripts/` フォルダ内の makefile を使用します。合成にはオープンソースのツールチェーンが使用され、Yosys が合成、nextpnr が配置・配線、Project Icestorm がビットストリーム生成を担当し、Lattice HX8k 評価ボード(`HX8k-EVN.mk`)や実験的な ECP5 サポート(`ECP5-EVN.mk`)などのターゲットをサポートしています。`hdl` ディレクトリにはバスファブ、グラフィックスユニット、hazard5 プロセッサコアの Verilog ソースが含まれており、`test` ディレクトリには Verilog テストベンチとソフトウェアケースを含む回帰テストが格納されています。現在、量産は iTead の 4 レイヤープロトタイピングサービスを活用し、10 ユニットを $65 で提供する Rev A PCB から開始されており、これらツールの合成と配線に使用されています。新たな Rev B PCB がゲートウェアの成熟に合わせて待機しています。この進化は、高レベルのソフトウェア開発と低レベルのハードウェアアーキテクチャを橋渡しする完全にカスタマイズ可能なプラットフォームを求める愛好家やエンジニアにとって意義のあるステップであり、現代のオープンソースコンピューティングエコシステムへの具体的な一瞥を提供しています。

2026/07/12 8:54

オデッセイ Linux

## Japanese Translation: 提供されたテキストには、本物のニュース記事、議論、または物語は含まれておらず、そのため、そのプレースホルダー的な性質を超えて主要メッセージを抽出することは不可能です。概して、コンテンツは「$ code」などの一般的なラベルを含む構造的テンプレートとして機能しだけであり、これは具体的な技術詳細のない抽象的なプログラミング概念を表しています。「$ constitution」や「$ governance」といった用語も、ここでは定義された法的・政治的文脈を欠いています。実際の出来事、意見、または事実主张を記述する文がないため、資料は歴史的背景、具体的な日付、または製品名を確立できていません。したがって、将来の動向に関する前向きな声明、予測、またはタイムラインも含まれていません。特定のユーザー、企業、産業を特定していないため、このコンテンツによって誰が影響を受ける可能性があるかを判断することはできません。記述言語が欠如していることは、いまだに核心的情報が表明されていないことを示しています。一言で言えば、文書は静的であり、読者が全体概要または潜在的な影響を理解しようとするとアクション可能な知見、データ、あるいは意味ある主題事項を全く含んでいません。 ## Text to translate The original summary is concise, accurate, and logically consistent with the provided key points. It clearly communicates that the document is a structural template devoid of substantive information. No improvements are necessary. ## Summary The provided text offers no substantive news story, argument, or narrative, making it impossible to derive a main message beyond its placeholder nature. Essentially, the content functions only as a structural template containing generic labels like "$ code," which represents abstract programming concepts without specific technical details, and terms such as "$ constitution" or "$ governance" that lack defined legal or political contexts here. Because there are no sentences describing actual events, opinions, or factual claims, the material fails to establish any historical background, specific dates, or product names. Consequently, the text contains no forward-looking statements, predictions, or timelines regarding future developments. Without identifying specific users, companies, or industries, it is impossible to determine who might be impacted by this content. The absence of descriptive language confirms that no core information has been articulated yet. In short, the document remains static and devoid of actionable intelligence, data, or any meaningful subject matter for a reader seeking to grasp an overall gist or potential consequences.