Skip to content

Split View: Dart 매크로 취소 그 후 1년 반 — 약속된 세 가지는 실제로 배송되었나

|

Dart 매크로 취소 그 후 1년 반 — 약속된 세 가지는 실제로 배송되었나

들어가며 — I/O 2026에서 사라진 단어

2026년 5월 Google I/O에 맞춰 나온 Dart 3.12 발표문에는 "매크로(macro)"라는 단어가 한 번도 나오지 않습니다. Dart 3.11 발표문(2026년 2월)에도, Dart 3.10 발표문(2025년 11월)에도 없습니다. 정확히 2년 전 I/O 2024에서 "수년간 설계에 투자했다"며 릴리스 발표문의 큰 부분을 할애해 소개했던 기능치고는 완전한 침묵입니다.

무슨 일이 있었는지는 알려져 있습니다 — 매크로는 2025년 1월에 공식 취소되었습니다. 이 글에서 하려는 건 그 사건의 복기가 아니라 사후 검증입니다. 취소문은 "대신 이걸 하겠다"는 약속 세 가지를 남겼고, 그로부터 1년 반이 지난 지금(Flutter 3.44.6 + Dart 3.12.2, 2026년 7월 9일 릴리스 기준)은 그 약속이 지켜졌는지 확인하기 좋은 시점입니다. 검증에는 2차 해설이 아니라 1차 소스만 씁니다 — dart.dev 블로그 원문(사이트 저장소의 마크다운), Dart SDK와 build_runner의 체인지로그, pub.dev 레지스트리 API, GitHub 이슈 상태.

타임라인 — 발표, 경고음, 취소

2024년 5월 14일, Dart 3.4. I/O 2024에서 매크로 프리뷰가 공개됩니다. 첫 매크로는 JSON 직렬화 보일러플레이트를 없애는 @JsonCodable() 하나였고, 계획은 3단계였습니다 — JsonCodable 프리뷰 → 반응이 좋으면 JSON 매크로를 stable로 → 최종적으로 커뮤니티가 자기 매크로를 정의할 수 있게 개방. 흥미로운 대목은 이 글이 데이터 클래스를 직접 언급한다는 점입니다. 데이터 클래스는 Dart 언어 저장소에서 가장 많은 표를 받은 기능 요청인데, 팀은 "무엇이 표준이어야 하는지 의견이 갈린다"며 언어에 내장하는 대신 매크로 시스템으로 커뮤니티가 각자 만들게 하는 쪽을 선택했다고 밝힙니다. 매크로는 처음부터 데이터 문제의 대리 해법이었습니다.

2024년 8월 6일, Dart 3.5. 로드맵 업데이트를 겸한 발표문에서 이미 경고음이 들립니다. 언어·컴파일러 팀 시간의 대부분을 매크로에 쓰고 있다면서도, hot reload 같은 핵심 사용 사례에 회귀를 일으킬 수 있어 신중하게 접근 중이고 "다음 단계를 공유하기까지 여러 분기가 더 필요할 것"이라고 적었습니다. 프리뷰 공개 후 석 달이 채 되기 전에 일정이 "여러 분기 뒤"로 물러난 것입니다.

2025년 1월 29일, 취소. Dart 팀의 Vijay Menon 명의로 An update on Dart macros & data serialization이 올라옵니다. 핵심 문장은 두 개입니다. "큰 기술적 장애물을 하나 풀 때마다 새 장애물이 나타났다", 그리고 "가까운 미래에 매크로를 배송하는 일은 없을 것이다(we will not be shipping macros in the foreseeable future)". 발표에서 취소까지 8개월 반이 걸렸습니다.

왜 죽었나 — 시맨틱 인트로스펙션과 hot reload의 충돌

취소문이 밝힌 이유는 성능도 아니고 인력도 아니고, 설계 목표 자체의 충돌입니다.

Dart 팀은 Rust의 절차적 매크로처럼 프로그램의 구문(syntax)만 보는 매크로로는 목표(데이터 직렬화 같은 문제를 제대로 풀기)에 부족하다고 판단했고, 컴파일 타임에 타입과 선언 구조까지 조회하는 깊은 시맨틱 인트로스펙션을 택했습니다. 문제는 그 선택의 비용이었습니다. 매크로가 프로그램의 의미 정보를 조회한다는 건, 코드가 바뀔 때마다 그 의미에 의존하는 매크로 출력물을 다시 계산해야 한다는 뜻입니다. 취소문의 표현을 빌리면 이 비용이 "stateful hot reload를 뜨겁게(hot) 유지하기 어렵게" 만들었고, 당시 구현은 편집 경험(정적 분석, 코드 완성)과 증분 컴파일(hot reload의 첫 단계) 양쪽 모두를 회귀시키고 있었습니다.

Flutter 개발자 입장에서 이 트레이드는 성립할 수 없는 거래입니다. Dart 팀 스스로 취소문에서 Dart의 정체성을 두 가지로 정의합니다 — 정적 언어 수준의 AOT 성능, 그리고 동적 언어 수준의 개발 사이클(hot reload). 매크로가 아무리 보일러플레이트를 없애 줘도 저장할 때마다 리로드가 굼떠진다면, Flutter가 React Native나 Compose 대비 내세우는 핵심 DX 자산을 갉아먹는 셈입니다. 기회비용을 언급하며 물러선 건 그래서 이해할 수 있는 결정입니다.

취소문은 대신 세 가지를 약속했습니다. (1) 데이터 처리를 위한 "더 맞춤형(bespoke)의 언어 기능들", (2) build_runner 개선, (3) 매크로의 부산물로 프로토타입한 augmentations의 독립 배송. 이제 하나씩 채점합니다.

성적표 1 — 데이터용 언어 기능: 부분 배송

취소 이후의 릴리스에서 작은 언어 기능들이 실제로 나왔습니다. 모두 SDK 체인지로그와 릴리스 발표문에서 확인됩니다.

  • null-aware elementsDart 3.8(2025년 5월 20일)에서 배송. 컬렉션 리터럴 안에서 null이면 통째로 빠지는 원소를 쓸 수 있게 합니다.
  • dot shorthandsDart 3.10(2025년 11월 12일)에서 배송. 문맥에서 타입이 추론될 때 LogLevel.error 대신 .error라고 쓰는 축약 문법입니다.
  • private named parametersDart 3.12(2026년 5월 20일)에서 배송. private 필드를 named 파라미터로 초기화할 때 강제되던 이니셜라이저 리스트 보일러플레이트를 없앱니다.
  • primary constructors — Dart 3.12에서 experimental로 공개(--enable-experiment=primary-constructors 플래그 필요). 그리고 아직 릴리스되지 않은 3.13의 SDK 체인지로그에는 이미 정식 언어 기능으로 기재되어 있습니다.

primary constructors가 이 계보의 본론입니다. 필드 선언과 생성자 파라미터를 클래스 헤더 한 줄로 합칩니다.

// 지금까지의 Dart — 두 필드짜리 클래스에 다섯 줄
class Point {
  final int x;
  final int y;
  Point(this.x, this.y);
}

// primary constructor — 3.12 experimental, 3.13 예정
class Point(final int x, final int y);

다만 채점을 정직하게 하면 "부분 배송"입니다. 매크로가 원래 풀려던 문제 — toJson/fromJson, ==/hashCode/copyWith가 자동으로 생기는 데이터 클래스 — 는 여전히 언어에 없습니다. dart-lang/language#314(Add data classes)는 2017년 10월에 열린 이래 이 글을 쓰는 시점에도 open이고, 추천 수 1,552개로 여전히 최상위권 요청입니다. 지금까지 배송된 건 보일러플레이트를 줄이는 문법이지, 직렬화 코드를 생성해 주는 무언가가 아닙니다. 그 일은 아래의 코드젠이 계속 맡습니다.

성적표 2 — build_runner: 가장 확실한 배송

매크로의 대안이 결국 "build_runner를 빠르게"였으므로, 여기가 제일 중요한 항목입니다. 그리고 여기는 숫자로 확인됩니다.

pub.dev 레지스트리 API의 발행 이력을 그대로 옮기면, 취소 전 build_runner는 사실상 유지보수 모드였습니다. 2.4.0(2023년 1월 18일)부터 2.4.15(2025년 2월 11일)까지 25개월간 릴리스 16개, 전부 패치 버전이고 마이너 범프가 하나도 없습니다. 취소 후가 변곡점입니다 — 2.5.0(2025년 6월 16일)부터 2.15.2(2026년 7월 13일)까지 13개월간 릴리스 30개, 마이너 라인만 11개가 나왔습니다. 취소문이 공언한 투자가 레지스트리 데이터에 그대로 찍혀 있는 셈입니다.

내용도 패치 수준이 아닙니다. build_runner 체인지로그 기준으로 2026년 상반기에만:

  • 2.13.0(2026년 3월) — "작은 초기 빌드 1.4배에서 큰 증분 빌드 4배 사이의 속도 향상". 벤치마크 전문은 릴리스 PR(dart-lang/build#4405)에 공개되어 있습니다.
  • 2.14.0(2026년 4월) — 분석용 파일 관리 개선으로 "증분 빌드 2배 추가 향상". 빌더 컴파일이 JIT에서 AOT 기본으로 바뀌었고(dart:mirrors를 쓰는 빌더는 JIT로 폴백), 초기 기동은 느려지는 대신 이후 빌드가 빨라지는 트레이드를 명시했습니다.
  • 2.15.0(2026년 4월) — 기본 메모리 사용량이 개선되었다며 --low-resources-mode 플래그 자체를 제거.

숫자에는 라벨을 붙여야 합니다. 위의 1.4배·4배·2배는 모두 Dart 팀 자체 벤치마크 수치입니다. 측정 조건은 해당 릴리스 PR의 벤치마크 스위트이고, 여러분의 코드베이스 — 빌더 조합, 패키지 수, 워크스페이스 구조 — 에서 같은 배수가 나온다는 보장은 없습니다. 4배라는 상한은 "큰 증분 빌드"라는 조건이 붙은 값입니다. 독립 재현 벤치마크는 아직 본 적이 없습니다. 그래도 방향 자체는 체인지로그 수십 개 항목이 일관되게 가리키고 있고, 개선의 존재까지 의심할 이유는 없습니다.

성적표 3 — augmentations: 미배송

취소문이 "매크로에서 프로토타입한 기능 중 독자적으로 가치가 있다, 독립 배송을 목표로 한다"고 했던 augmentations(한 선언을 다른 파일에서 증강하는 기능 — 코드젠 출력물을 part 파일보다 매끄럽게 붙이는 기반)는, 이 글을 쓰는 시점 기준 어느 릴리스에도 실리지 않았습니다. 추적 이슈 dart-lang/language#4154는 여전히 open이고(2026년 2월에 마지막 갱신), 미출시 3.13 구간까지의 SDK 체인지로그에도 augmentation 항목은 없습니다. 세 약속 중 유일하게 아무것도 도착하지 않은 항목입니다.

참고로 build_runner 개선의 상위 추적 이슈(dart-lang/build#3800, "Faster dev cycle")도 아직 open입니다 — 배송이 진행 중이라는 뜻이지, 끝났다는 뜻은 아닙니다.

죽은 기능이 남긴 흔적들

취소가 얼마나 철저했는지는 부산물 정리에서 보입니다. 전부 지금 확인 가능한 상태입니다.

  • pub.dev의 macros 패키지(0.0.1에서 멈춤)와 JsonCodable을 담았던 json 패키지(0.20.4, 2024년 12월이 마지막)는 둘 다 discontinued 마크가 붙었습니다.
  • 문서 페이지였던 dart.dev/language/macros 는 이제 취소 블로그 글로 301 리다이렉트됩니다. 기능 문서의 URL이 그 기능의 부고 기사로 연결되는, 흔치 않은 풍경입니다.

한편 매크로가 대체하려던 것들은 멀쩡히 살아 있습니다. pub.dev 기준 json_serializable은 6.14.0(2026년 5월 15일), freezed는 3.2.5(2026년 2월 3일)로 계속 릴리스 중입니다. 2026년의 Dart 데이터 직렬화는 여전히 코드젠이고, 달라진 건 그 코드젠을 돌리는 엔진이 빨라졌다는 점입니다.

그래서 지금 무엇을 해야 하나

매크로를 기다리며 미뤄 둔 결정이 있다면 끝내십시오. 공식 입장은 "foreseeable future에 없다"이고, 최근 세 번의 릴리스 발표문(3.10·3.11·3.12)에서 매크로는 언급조차 되지 않습니다. 장기 메타프로그래밍 탐구 이슈(#1482)가 열려 있긴 하지만, 로드맵에 있는 건 아무것도 없습니다.

build_runner를 최신으로 올리는 건 값싼 이득입니다. 2.4.x에 머물러 있는 프로젝트라면 2.15.x까지 사이에 성능 개선이 여러 층 쌓여 있습니다. 다만 2.14.0부터 AOT 컴파일이 기본이라 첫 기동이 느려질 수 있고, dart:mirrors 의존 빌더가 있으면 JIT 폴백이 일어난다는 점은 알고 올리는 게 좋습니다.

primary constructors는 아직 켜지 마십시오. 3.12에서는 experimental 플래그이고, experimental 기능은 릴리스 사이에 문법이 바뀔 수 있습니다. 3.13 체인지로그에 정식 기재된 건 맞지만 3.13은 아직 릴리스되지 않았습니다 — 미출시 체인지로그는 계획이지 약속이 아닙니다.

freezed/json_serializable 스택을 걷어낼 이유는 없습니다. 언어가 데이터 클래스를 내장하는 날이 오기 전까지(#314는 2017년부터 열려 있습니다), 코드젠은 Dart의 데이터 스토리 그 자체입니다. Flutter 생태계 전반에서 이 스택이 차지하는 위치는 크로스플랫폼 비교 글에서 다룬 그대로입니다.

마치며

기능 취소는 보통 조용히 일어납니다. 이슈가 몇 년 방치되다 닫히고, 문서가 슬그머니 사라지는 식으로. Dart 매크로 취소가 복기할 가치가 있는 건 그 반대였기 때문입니다 — 이유(시맨틱 인트로스펙션의 컴파일 타임 비용이 hot reload와 양립 불가)를 기술적으로 설명했고, 대안 세 가지를 명시했고, 그중 둘은 1년 반 뒤 릴리스와 레지스트리 데이터로 확인 가능한 형태로 배송되고 있습니다.

동시에 채점표는 미완입니다. augmentations는 도착하지 않았고, 데이터 클래스는 여전히 이슈 트래커의 1위 요청이며, build_runner의 속도 수치는 아직 팀 자체 측정뿐입니다. 매크로의 죽음이 남긴 교훈이 있다면 이것일 겁니다 — hot reload는 Dart가 어떤 언어 기능과도 바꾸지 않는 불가침 자산이라는 것, 그리고 그 제약 아래에서 Dart의 메타프로그래밍은 당분간 "더 빠른 코드젠"이라는 답에 머문다는 것.

참고 자료

Dart Macros, One and a Half Years After Cancellation — Did the Three Promises Actually Ship?

Introduction — The Word That Vanished at I/O 2026

The Dart 3.12 announcement, timed to Google I/O in May 2026, never mentions the word "macro" once. Neither does the Dart 3.11 announcement (February 2026), nor the Dart 3.10 announcement (November 2025). That's total silence for a feature that, exactly two years earlier at I/O 2024, was introduced with a large chunk of the release announcement devoted to it, under the banner of "years of investment in the design."

What happened is well known — macros were officially canceled in January 2025. This post isn't a retrospective on that event; it's a post-hoc verification. The cancellation post left three "we'll do this instead" promises, and now, a year and a half later (as of Flutter 3.44.6 + Dart 3.12.2, released July 9, 2026), is a good time to check whether those promises were kept. The verification uses only primary sources, not secondary commentary — the original dart.dev blog posts (the markdown in the site's repository), the Dart SDK and build_runner changelogs, the pub.dev registry API, and GitHub issue status.

Timeline — Announcement, Warning Signs, Cancellation

May 14, 2024, Dart 3.4. The macros preview was unveiled at I/O 2024. The first macro was a single @JsonCodable() that eliminated JSON-serialization boilerplate, and the plan had three stages — a JsonCodable preview → promote the JSON macro to stable if reception was good → eventually open the system so the community could define its own macros. The interesting part is that the post directly names data classes. Data classes are the most-upvoted feature request in the Dart language repository, and the team said that because "opinions differ on what the standard should be," they chose to let the macro system let the community build its own instead of building it into the language. From the start, macros were a proxy solution to the data-class problem.

August 6, 2024, Dart 3.5. Warning signs are already audible in the announcement that doubled as a roadmap update. It says that while most of the language and compiler team's time is going into macros, they're proceeding carefully because macros could regress core use cases like hot reload, and that "it will likely be several more quarters before we can share next steps." Less than three months after the preview shipped, the timeline had already slipped to "several quarters out."

January 29, 2025, cancellation. An update on Dart macros & data serialization goes up under the byline of Dart team member Vijay Menon. Two sentences carry the weight: "each time we solved one major technical hurdle, a new one appeared," and "we will not be shipping macros in the foreseeable future." Eight and a half months passed between the announcement and the cancellation.

Why It Died — Semantic Introspection Collided With Hot Reload

The reason the cancellation post gives isn't performance, and it isn't staffing — it's a collision between the design goals themselves.

The Dart team judged that macros seeing only a program's syntax, the way Rust's procedural macros do, wouldn't be enough to properly solve the goal (problems like data serialization), so they chose deep semantic introspection that queries types and declaration structure at compile time. The problem was the cost of that choice. A macro querying a program's semantic information means that every time code changes, any macro output that depends on that semantics has to be recomputed. In the cancellation post's words, this cost made it "hard to keep stateful hot reload hot," and the implementation at the time was regressing both the editing experience (static analysis, code completion) and incremental compilation (hot reload's first stage).

From a Flutter developer's standpoint, this trade doesn't pencil out. The Dart team itself defines Dart's identity in the cancellation post as two things — AOT performance on par with a static language, and a development cycle (hot reload) on par with a dynamic language. No matter how much boilerplate macros eliminate, if reload gets sluggish on every save, that eats into the core DX asset Flutter holds up against React Native or Compose. Backing off while citing opportunity cost is, on those terms, an understandable call.

Instead, the cancellation post promised three things: (1) "more bespoke language features" for handling data, (2) build_runner improvements, and (3) shipping augmentations — a byproduct prototyped alongside macros — independently. Now let's grade them one by one.

Scorecard 1 — Language Features for Data: Partially Shipped

Small language features did actually land in releases after the cancellation. All of them are confirmed in the SDK changelog and the release announcements.

  • null-aware elements — shipped in Dart 3.8 (May 20, 2025). Lets you write an element inside a collection literal that's dropped entirely if it's null.
  • dot shorthands — shipped in Dart 3.10 (November 12, 2025). A shorthand syntax that lets you write .error instead of LogLevel.error when the type can be inferred from context.
  • private named parameters — shipped in Dart 3.12 (May 20, 2026). Removes the initializer-list boilerplate that used to be forced when initializing a private field via a named parameter.
  • primary constructors — released as experimental in Dart 3.12 (requires the --enable-experiment=primary-constructors flag). It's already listed as a full language feature in the SDK changelog for the as-yet-unreleased 3.13.

Primary constructors are the main event in this lineage. They fold field declarations and constructor parameters into a single line in the class header.

// Dart until now — five lines for a two-field class
class Point {
  final int x;
  final int y;
  Point(this.x, this.y);
}

// primary constructor — 3.12 experimental, planned for 3.13
class Point(final int x, final int y);

Graded honestly, though, this is "partially shipped." The problem macros originally set out to solve — data classes that automatically generate toJson/fromJson, ==/hashCode/copyWith — is still absent from the language. dart-lang/language#314 (Add data classes) has been open since October 2017 and remains open as of this writing, still one of the top requests with 1,552 upvotes. What's shipped so far is syntax that reduces boilerplate, not something that generates serialization code for you. That job still belongs to the codegen covered below.

Scorecard 2 — build_runner: The Clearest Delivery

Since the alternative to macros ultimately came down to "make build_runner faster," this is the item that matters most. And this one is confirmed by numbers.

Carrying the publication history from the pub.dev registry API over as-is, build_runner before the cancellation was effectively in maintenance mode. From 2.4.0 (January 18, 2023) to 2.4.15 (February 11, 2025), there were 16 releases over 25 months, all patch versions, with not a single minor bump. Things inflect after the cancellation — from 2.5.0 (June 16, 2025) to 2.15.2 (July 13, 2026), 30 releases over 13 months, 11 of them minor-line bumps. The investment the cancellation post promised is stamped right into the registry data.

The content isn't patch-level either. Just in the first half of 2026, per the build_runner changelog:

  • 2.13.0 (March 2026) — "a speedup ranging from 1.4x on small initial builds to 4x on large incremental builds." The full benchmark is published in the release PR (dart-lang/build#4405).
  • 2.14.0 (April 2026) — "an additional 2x on incremental builds" from improved file management for analysis. Builder compilation switched from JIT to AOT by default (builders using dart:mirrors fall back to JIT), and the post explicitly notes the tradeoff: slower initial startup in exchange for faster subsequent builds.
  • 2.15.0 (April 2026) — removed the --low-resources-mode flag entirely, citing improved baseline memory usage.

Numbers need a label attached. The 1.4x, 4x, and 2x above are all the Dart team's own benchmark figures. The measurement conditions are the benchmark suite in that release PR, and there's no guarantee your codebase — your combination of builders, package count, workspace layout — will produce the same multiplier. The 4x ceiling comes with the condition "large incremental build" attached. I haven't yet seen an independently reproduced benchmark. That said, the direction itself is consistently pointed to by dozens of changelog entries, and there's no reason to doubt that the improvement exists.

Scorecard 3 — Augmentations: Not Shipped

Augmentations — the feature that lets one declaration be augmented from another file (a foundation for splicing in codegen output more smoothly than part files), which the cancellation post said "has independent value among the features prototyped in macros, and we aim to ship it independently" — hadn't landed in any release as of this writing. The tracking issue dart-lang/language#4154 is still open (last updated February 2026), and there's no augmentation entry in the SDK changelog even through the as-yet-unreleased 3.13 range. Of the three promises, this is the only one where nothing has arrived at all.

For reference, the parent tracking issue for the build_runner improvements (dart-lang/build#3800, "Faster dev cycle") is also still open — meaning delivery is ongoing, not that it's finished.

The Traces a Dead Feature Left Behind

How thorough the cancellation was shows up in how the byproducts were cleaned up. All of this is verifiable right now.

  • pub.dev's macros package (stalled at 0.0.1) and the json package that held JsonCodable (0.20.4, last updated December 2024) both carry a discontinued mark.
  • The documentation page at dart.dev/language/macros now 301-redirects to the cancellation blog post. It's an unusual sight — a feature-documentation URL leading straight to that feature's obituary.

Meanwhile, the things macros were meant to replace are alive and well. Per pub.dev, json_serializable is still releasing, at 6.14.0 (May 15, 2026), and freezed at 3.2.5 (February 3, 2026). Dart data serialization in 2026 is still codegen — what's changed is that the engine running that codegen got faster.

So What Should You Do Now

If you've been postponing a decision while waiting for macros, close it out. The official position is "not in the foreseeable future," and macros aren't even mentioned in the last three release announcements (3.10, 3.11, 3.12). A long-term metaprogramming exploration issue (#1482) is open, but nothing is on the roadmap.

Upgrading build_runner to the latest is a cheap win. If your project is still stuck on 2.4.x, there are multiple layers of performance improvements stacked up on the way to 2.15.x. Just be aware before you upgrade that first startup can get slower since AOT compilation became the default from 2.14.0 on, and that a builder depending on dart:mirrors will fall back to JIT.

Don't turn primary constructors on yet. In 3.12 it's still behind an experimental flag, and experimental features can change syntax between releases. It's true that it's formally listed in the 3.13 changelog, but 3.13 hasn't been released yet — an unreleased changelog is a plan, not a promise.

There's no reason to rip out your freezed/json_serializable stack. Until the day the language builds in data classes (#314 has been open since 2017), codegen is Dart's data story, full stop. Where this stack sits within the broader Flutter ecosystem is covered as-is in React Native vs Flutter 2025: The Complete Cross-Platform Mobile Development Guide.

Closing

Feature cancellations usually happen quietly — an issue sits neglected for years and then gets closed, documentation quietly disappears. The Dart macros cancellation is worth reviewing precisely because it was the opposite — it explained the reason (semantic introspection's compile-time cost being incompatible with hot reload) technically, named three alternatives explicitly, and one and a half years later, two of those three are shipping in a form verifiable through release and registry data.

At the same time, the scorecard is incomplete. Augmentations hasn't arrived, data classes remain the top-ranked request on the issue tracker, and build_runner's speed numbers are still team-measured only. If there's a lesson left behind by the death of macros, it's probably this — hot reload is an inviolable asset Dart won't trade for any language feature, and under that constraint, Dart's metaprogramming will, for the time being, stay at the answer of "faster codegen."

References