Tree-sitter のおかげで、より充実した R プログラミング体験をお楽しみください。

2026/04/17 6:14

Tree-sitter のおかげで、より充実した R プログラミング体験をお楽しみください。

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

要約

Japanese Translation:

Tree-sitter 文法の "treesitter-r" リポジトリへの統合は、Jim Hester および Kevin Ushey が築いた基盤を、Davis Vaughan の仕事によってさらに進展させ、R コードの作成、保守、分析のあり方を変革しました。この成果は useR! 2024 で表彰され、主に Positron における IDE エクスペリエンスの改善(Ark を通じた自動補完や、GitHub の検索結果において関数の定義を特定するなどのナビゲーション機能の向上など)を通じて、開発者に高度な機能を解き放ちました。個別の編集を越えて、Tree-sitter は構造的解析ツールの広いエコシステムを可能にしています:Air と Jarl は高速なフォーマットとLintingを提供し、

{treesitter}
はR環境内でコードの解析や構文ツリーの可視化を、
{gander}
はLLMとの相互作用を強化します。さらに、
{igraph.r2cdocs}
および
{pkgdepends}
といった専門パッケージはそれぞれCラッパーおよび依存関係を検出します。また、
{ts}
{muttest}
difftastic
、そしてuseR!で表彰された実績といったツールにより、Tree-sitterの有用性は設定ファイルの解析、突然変異テスト、構造的コード差分へ拡張され、単純なテキスト編集からR開発向けに洗練された構造的分析へと活気づいたパラダイムシフトを促進しました。

本文

約 2 年前、Jim Hester氏と Kevin Ushey氏の研究成果を受け継ぎ、Davis Vaughan氏はRコミュニティに非常にインパクトのあるJavaScriptファイル(Tree-sitterパースャー生成器用のR言語用文法)を完成させました。その功績はuseR! 2024でのプレゼンテーションにおいて拍手に迎えられました!👏 では、 Davis Vaughan氏はこのJavaScriptファイルに含まれる「文法規則」が称賛されたのでしょうか?😅 いいえ、聴衆が興奮したのは、このファイルによって実現したR開発者体験(Developer Experience, DX)の向上でした。

Tree-sitterを基盤としたツール群は、Airによるコード整形やJarlによるlinting(静的解析)、Positron IDEにおけるオートコンプリートやカーソルホバー時のヘルプ提示、GitHub上のR関連リポジトリでの検索機能の改善など、多岐にわたる利便性をもたらしています。

本稿では、まずTree-sitterとは何かを解説し、さらにTree-sitterを基盤としたツールがR開発ワークフローにどのような恩恵をもたらすかを詳述します。

コード解析:Tree-sitterとは?

Tree-sitterはC言語で書かれたコードパースャー(解析器)生成器です。そのラッパー(バインディング)は、RustやR(!)など複数の言語に存在します。

少し時間を遡りましょう。「コードをパースする」とは具体的に何を意味するかというと、例えば文字列

"a <- mean(x, na.rm = TRUE)"
が与えられた際、どの部分を関数名 (
mean
) と見なし、どの部分を引数名 (
na.rm
) または論理値 (
TRUE
) と識別できるのか、を正しく理解することです。これを行うには、コードを「パース木(Parse Tree)」へと変換する必要があります。Rコードを読む際に私たちは無意識にこれを頭の中で行っています😸。

もちろん、R自体はその独自の文法のおかげでRコードの解析が可能です。例えば、R固有のパイプ演算子

%>%
を導入したコミットを見てもわかる通り、この機能を実装するためにはRの構文を拡張する必要があり、結果としてRの文法そのものが変更されました。

以下は、Rコードを解析するための

parse()
関数と、解析結果を抽出するための
getParseData()
関数の使用例です。

parse(
  text = "a <- mean(x, na.rm = TRUE)",
  keep.source = TRUE
) |>
  getParseData()
#>    line1 col1 line2 col2 id parent                token terminal  text
#> 23     1    1     1   26 23      0                 expr    FALSE      
#> 1      1    1     1    1  1      3               SYMBOL     TRUE     a
#> 3      1    1     1    1  3     23                 expr    FALSE      
#> 2      1    3     1    4  2     23          LEFT_ASSIGN     TRUE    <-
#> 21     1    6     1   26 21     23                 expr    FALSE      
#> 4      1    6     1    9  4      6 SYMBOL_FUNCTION_CALL     TRUE  mean
#> 6      1    6     1    9  6     21                 expr    FALSE      
#> 5      1   10     1   10  5     21                  '('     TRUE     (
#> 7      1   11     1   11  7      9               SYMBOL     TRUE     x
#> 9      1   11     1   11  9     21                 expr    FALSE      
#> 8      1   12     1   12  8     21                  ','     TRUE     ,
#> 13     1   14     1   18 13     21           SYMBOL_SUB     TRUE na.rm
#> 14     1   20     1   20 14     21               EQ_SUB     TRUE     =
#> 15     1   22     1   25 15     16            NUM_CONST     TRUE  TRUE
#> 16     1   22     1   25 16     21                 expr    FALSE      
#> 17     1   26     1   26 17     21                  ')'     TRUE     )

あるいは、Gábor Csárdi氏による

{xmlparsedata}
パッケージを用いて、同じデータをXML形式に変換することもできます。

parse(
  text = "a <- mean(x, na.rm = TRUE)",
  keep.source = TRUE
) |>
  xmlparsedata::xml_parse_data(pretty = TRUE) |>
  xml2::read_xml() |>
  as.character() |>
  cat()
#> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
#> <exprlist>
#>   <expr line1="1" col1="1" line2="1" col2="26" start="28" end="53">
#>     <expr line1="1" col1="1" line2="1" col2="1" start="28" end="28">
#>       <SYMBOL line1="1" col1="1" line2="1" col2="1" start="28" end="28">a</SYMBOL>
#>     </expr>
#>     <LEFT_ASSIGN line1="1" col1="3" line2="1" col2="4" start="30" end="31">&lt;-</LEFT_ASSIGN>
#>     ... (省略)

どちらのケースでも、

LEFT_ASSIGN
SYMBOL_FUNCTION_CALL
といった単語認識(トークン化)が行われます。コードを実行する前に解析を行うことは不可欠ですが、解析されたコードは他の用途にも活用可能です。例えば、壊れやすい正規表現に依存せずコードを分析する(特定の関数と呼び出しているか?)、コード構造を理解して移動する(関数の呼び出し元からその定義へ飛ぶ)、あるいはコードを書き換える(ある関数の出現箇所を別の関名に置き換えるなど)といった応用が可能になります。

Tree-sitterは、この同じコード解析作業を行いますしかし、その速度は格段に速いです。特に「増分パース(incremental parsing)」機能を備えている点が大きいですが、これはエディタ上で入力しながらシンタックスツリーを逐次更新する際に極めて重要です。Tree-sitterは文法さえ存在すればどの言語のコードでも解析可能であり、「ローゼッタストーン」といったプラグインのような役割を果たします。実際、多くの言語で利用されており、その周りに多数のツールが構築されています。

新しい言語をTree-sitterに「学習」させるには、その言語の構文定義を含むファイル(文法)を与える必要があります。ここで言及したDavis Vaughan氏らのJavaScriptファイルが活躍する場所です。Rの文法をTree-sitterが要求する形式へ翻訳した

treesitter-r
リポジトリこそが、本稿で紹介する全てのツールの基盤となっています。これらはすべてRコードを入力とするツールです。

以下は、前述のコードを解析するための

{treesitter}
Rパッケージを使った手順です。この
{treesitter}
パッケージは、Tree-sitterをR環境から直接利用できるようにします。Rコードを解析するには、
{treesitter.r}
パッケージからの
language()
関数を必要とします。

library(treesitter)
#> 
#> Attaching package: 'treesitter'
#> The following object is masked from 'package:base':
#> 
#>     range

language <- treesitter.r::language()
parser <- parser(language)
text <- "a <- mean(x, na.rm = TRUE)"
parser_parse(parser, text)
#> <tree_sitter_tree>
#> 
#> ── Text ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
#> a <- mean(x, na.rm = TRUE)
#> 
#> ── S-Expression ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
#> (program [(0, 0), (0, 26)]
#>   (binary_operator [(0, 0), (0, 26)]
#>     lhs: (identifier [(0, 0), (0, 1)])
#>     operator: "<-" [(0, 2), (0, 4)]
#>     rhs: (call [(0, 5), (0, 26)]
#>       function: (identifier [(0, 5), (0, 9)])
#>       arguments: (arguments [(0, 9), (0, 26)]
#>         open: "(" [(0, 9), (0, 10)]
#>         argument: (argument [(0, 10), (0, 11)]
#>           value: (identifier [(0, 10), (0, 11)])
#>         )
#>         (comma [(0, 11), (0, 12)])
#>         argument: (argument [(0, 13), (0, 25)]
#>           name: (identifier [(0, 13), (0, 18)])
#>           "=" [(0, 19), (0, 20)]
#>           value: (true [(0, 21), (0, 25)])
#>         )
#>         close: ")" [(0, 25), (0, 26)]
#>       )
#>     )
#>   )
#> )

Tree-sitterは下図のツール群の中核をなすエンジンであり、これら全てのツールはTree-sitterとそれに対するR言語用の文法に依存しています。一部のツールはコマンドラインインターフェース(CLI)形式のものであり、その他はRパッケージです。

コードのインタラクティブ閲覧:Positron IDE, GitHub

聴衆がDavis Vaughan氏を称賛した真の理由は、Tree-sitter用のR文法がGitHubへデプロイされ、結果としてGitHub上でRコードを閲覧する体験感が(JavaScriptコードのように)ほぼ同等になったという事実を説明した点にあります。例えば、リポジトリ内で関数名を検索すれば、検索結果にその関数の定義も表示されます。Davis氏のスライド(PDF版も用意されています)をご覧いただくか、以下の変形例動画をご覧ください。Rの

vetiver
リポジトリから「vetiver_model」と入力して検索バーを検索すると、関数定義が最初の結果として表示され、クリックすることでその定義ページに遷移できます。

また、Positron IDEで使用されるRカーネルであるArkがTree-sitterを活用している点も非常に有用です。Arkを通じてPositronではオートコンプリートやカーソルホバー時のヘルプ提示が可能となります。以下の動画は、Positron内でパイプラインの次のステップまで選択範囲を拡張する方法を示しています。

Tree-sitterによるコード検索・閲覧機能についてはDavis氏のスライドにも掲載されています。さらに、2024年のposit会議でLionel Henry氏とDavis Vaughan氏が発表した「Ark」に関するセッション(特にコードアシストに関するパート)も参照ください。 Emacsなどの開発環境でもTree-sitterへのサポートが実装されています。

コードの検索・閲覧

{treesitter}
RパッケージとTree-sitterクエリ構文を活用することで、Rコードの解析と検索が可能です。Simon Couch氏による
{gander}
パッケージはLLM(大規模言語モデル)を駆使してRコードを書く際の体験感を向上させるために利用されるため、その依存関係として
{treesitter}
が必要です。また、
{igraph}
パッケージ向けの
{roxygen2}
拡張機能である
{igraph.r2cdocs}
{treesitter}
Rパッケージを利用しており、全ての
igraph
Rコードを解析することで、エクスポートされた関数において(直接的または間接的に)末尾が
_impl
で終わる関数を呼び出しているかどうかを検出し、R関数のマニュアルからC版の
igraph
関数のドキュメントへリンク付けできるようになっています。

さらに、依存関係をファイル内で検出する

{pkgdepends}
パッケージもTree-sitter(C)を呼び出しています。以下は
saperlipopette
Rパッケージのソースコードに対して実行した結果です。

pkgdepends::scan_deps(
  "../../../../../CHAMPIONS/saperlipopette",
  "../../../../../CHAMPIONS"
)
#> 
#> Dependencies:
#> + brio           @ R/blame.R, R/check-editor.R, R/clean-dir.R, ...
#> + cli            @ inst/exo_bisect-Rprofile.en.R, ...
#> + devtools       @ saperlipopette.Rproj
#> + fs             @ R/blame.R, ...
#> + gert           @ inst/exo_check_editor-Rprofile.en.R, ...
#> + knitr          @ README.Rmd
#> ... (省略)

ast-grep
は、Tree-sitterを基盤としたコード検索および書き換えツールであり、Tree-sitterの構文よりも明確で使いやすいクエリ言語を提供します。名前の響きからgrepを連想しますが、
ast-grep
を使うと壊れやすい正規表現を記述する必要はありません😸。Etienne Bacher氏による
{astgrepr}
はRust版の
ast-grep
ラッパーであり、Etienne氏のコードリファクタリングツール
{flir}
で利用されています。また、Emil Hvitfeldt氏が執筆した有益なブログ記事には、Claudeへの指示文として
ast-grep
の使用法を文書化する方法が紹介されています。

コードの整形とLinting:Air, Jarl

コマンドラインインターフェース(CLI)の話に戻りましょう。

AirはDavis Vaughan氏とLionel Henry氏によって作成された、Rustで作られたTree-sitterを基盤としたCLIツールです。このツールはコードの整形(フォーマッティング)作業を非常に高速に行います。

JarlはEtienne Bacher氏によって作成され、Air(つまりTree-sitter)を基盤とするRust製のCLIツールです。Jarlはコードのlintingと修正を行い、極めて高速に動作します。さらに到達不可能なコード、未使用関数、重複した関数定義などの検出も可能です。

これらの例において、

{treesitter}
RパッケージをラップするRパッケージを作成するよりも、Tree-sitterのバインディングをラップしたRust製CLIツールの作成の方が効率的である理由は以下の通りです:

  • Rust製のCLIはコード編集速度が極めて速い;
  • CLIツールは主流のIDE向けの拡張機能に統合されやすい(例:Positronなど);
  • CI環境へのインストールにおいて、Rパッケージが必要とする「R環境そのもののセットアップ」を回避できるため、CLIの方が扱いやすい。

その他、少しばかり探検したが興味深いツールもいくつか紹介しておきましょう。

設定:TOML/JSONの解析用
{ts}

Gábor Csárdi氏による

{ts}
パッケージは、編集および操作用の2つのRパッケージの中核を担っています:

  • TOML向け
    {tstoml}
  • JSON向け
    {tsjson}

これら2つのパッケージは、既存のR用解析器と比較して、コメント情報を保持したまま処理するという特徴があります。

コードのテスト:
{muttest}

突然変異テスト(Mutation Testing)は、例えばコード内の

+
をランダムに
-
に置き換える(突然変異させる)等操作を行い、テストを実行することでその変異を検知できるかを確認する手法です。Jakub Sobolewski氏による
{muttest}
パッケージは、そのような突然変異テストを行うためのRパッケージであり、
{treesitter}
Rパッケージへの依存関係を持ちます。

コードの差分表示:
difftastic

Wilfred Hughes氏によって開発されたCLIツール「

difftastic
」は、「構文を理解する構造ベースの差分表示ツール」です✨。つまり、
difftastic
は行単位の比較や「単語」単位の比較だけでなく、変更された行の前後(デフォルトでは3行)を見て実際のシンタックス構造を比較します。さらに素晴らしいことに、R言語自体もそのまま理解可能(Out of the box support)です。Rコードを使った差分表示の実例を含むブログ記事をご覧ください。

結論:今後さらに?

本稿では、RにおけるTree-sitter基盤のツール群について概観しました。なお、このエコシステムは非常に活発に開発が進められているため、ツールの登場や退場も繰り返されます。しかし、一般的なパースャー生成器にR言語の文法を取り入れることによる恩恵(優れた機能の提供)という点については間違いなく真実であり続けます。もしかすると、既存のツールへのコントリビューションや新たなツールの作成を通じて、皆様もこのエコシステムに貢献されるかもしれませんね?

同じ日のほかのニュース

一覧に戻る →

2026/04/16 23:23

Claude オプス 4.7

## Japanese Translation: Claude Opus 4.7 は、すべての Claude プラットフォーム、API、Amazon Bedrock、Google Cloud Vertex AI、Microsoft Foundry において大幅な向上と一般利用を開始しました。先進的なソフトウェア工学における主要な飛躍として、長期的自律性と自己検証機能が強化された Opus 4.6 を引き継ぎます。モデルのビジョン能力も著しく向上し、最大約 375 万画素(従来の 3 倍以上)までの画像に対応します。料金は Opus 4.6 と同一の、入力トークン当たり 5 ドル、出力トークン当たり 25 ドルで維持され、より微細なトレードオフ制御を可能にする新たな"xhigh"レベルが導入されました。内部評価では、93 タスクからなるベンチマークにおけるコーディング精度が 13% 向上し、4 つの以前は解決不能だったタスクを完遂することを実現するなど大きな進歩が見られます。また、「General Finance」モジュールでは、Opus 4.6 の 0.767 に対し 0.813 という大幅な金融分析能力の進歩、CursorBench(明確回答率 70%)や Complex Multi-step Workflows(+14%)といったベンチマークでも著しい向上を記録。さらに Rakuten-SWE-Bench 上の本番タスク解決数は 3 倍に増加し、コード品質でも二位桁の改善が実現しました。これらの進展は、Devin などのような環境での長期的自律性を可能にし、Replit においては同等かそれ以下のコストで高性能な実行を達成します。新機能としては、「task budgets」ベータ版およびバグレビュー専用の `/ultrareview` スラッシュコマンドが含まれます。本リリースは「Project Glasswing」の一貫した慎重な安全アプローチと整合しており、自動的な防護機構により高リスクのサイバーセキュリティ用途をブロックすると同時に、正当な研究者に新しい Cyber Verification プログラムへの参加を呼びかけています。結論として、Opus 4.7 は金融分析や工学など重要分野における一貫性の新基準を設定し、次世代 AI ツールの採用準備が整った企業向けに、強化されたパフォーマンスと戦略的リソース管理を提供します。

2026/04/17 2:12

ほぼすべてのことに適用可能なコードックス。

## Japanese Translation: OpenAI は、Codex アプリに対する主要なアップデートを導入し、それを受動的アシスタントからユーザーのコンピュータを直接操作する能動的で自律的なエージェントへと変革します。macOS 上の高度なバックグラウンド機能(カーソル制御[見る、クリック、打つ]とマルチエージェント並列処理)を活用し、Codex はプルリクエストのレビュー、SSH を介したリモート環境の管理、PDF やスプレッドシートなどのリッチなファイルプレビューを開くことができます。アプリ内に統合されたブラウザを通じて、ユーザーは Web ページ上に直接コメントを付けることで正確な指示を提供できます。新しいシステムには、個人のコンテキストと好みを記憶するためのメモリレイヤーが追加され、90 以上のプラグインにより GitHub、GitLab、Atlassian、CircleCI、CodeRabbit などの外部ツールとの接続が可能になります。Codex は désormais、来週の日数や週間を跨いで作業をスケジューリングし、自律的に目覚めることで長期タスクをサポートします。また、Google Docs、Slack、Notion、コードベース内のオープンなコメントに基づき、能動的にアクションを提案します。さらに、このアップデートには gpt-image-1.5 が統合され、製品コンセプト、フロントエンドデザイン、マockアップ、ゲームなどの同じワークフロー内で画像の生成と反復を行うことができます。今日、ChatGPT にサインインしたデスクトップユーザー向けにロールアウトされており、これらの機能は間もなく Enterprise、Edu、EU、UK アカウントにも拡大されます。

2026/04/17 6:56

グイが、デュオテープ、古いカメラ、およびCNCマシンを組み合わせて、AIを駆使したハードウェアハッカー用の腕を作成しました。

## Japanese Translation: **改善されたサマリー:** 本テキストの主なメッセージは、電子機器に対する安全なピンプローブを可能化することを目的としたソースアベイラブルなハードウェアハッキング自動化スタックである「AutoProber」の導入です。標準的なツールが盲目的に進む可能性に対して、AutoProber は CNC モーション制御、光学顕微鏡、リアルタイムオシロスコープ監視を「安全第一」というアーキテクチャに統合します。本システムはプロジェクトを読み込み、ハードウェアと接続し、軸をキャリブレーションし、エージェントまたはダッシュボードを使用してターゲットを検出およびアノテーション済みマップをステッチします。特に重要なのは、安全が独立したチャンネル(オシロスコープ チャンネル 4)によって執行されており、電圧を連続的に監視することであり、あらゆる曖昧さ、アラート、またはトリガーが発生した場合に自動回復なく即座に停止し、作業者の介入を必須としている点です。 GRBL 互換 CNC ミル(例:SainSmart Genmitsu)、USB 顕微鏡、および Siglent オシロスコープを基盤とし、本スタックは現在、特定の安全制約付きで制限リリースカンドイドとして存在しています:コントロールダッシュボードが信頼できないネットワークに露出させてはならないこと、および商用ライセンス発行にはメールでの申請が必要であることが含まれます。本プロジェクトは、複雑なプローブ作業中の機器破損や人身傷害を防ぐために、ダッシュボード上でのプローブターゲット承認などの作業者による専用の監督を強調しており、ハードウェアハッキングにおける標準的な自動化ワークフローの前提を根本的に変化させます。