{"article":{"slug":"unrolled-code","title":"Unrolled Code","subtitle":null,"summary":"Starting from grubby, a minimal Ruby static site generator written in a plain unrolled style, this Noteflakes post compares it to how ERB and Papercraft compile templates, then proposes a quote/unquote mechanism for Ruby code generation and discusses walking the line between Rails-style abstraction and machine performance.","content_type":"blog_post","language":"en","canonical_url":"https://noteflakes.com/articles/2026-10-07-unrolled-code","author":{"name":null,"url":null,"person_slug":null,"person_url":null},"authored_by":"human","publisher":{"name":"Noteflakes","url":"https://noteflakes.com/","listing_slug":null,"listing":null},"topics":[{"name":"Ruby","slug":"ruby","url":"https://listedarticles.com/topics/ruby"},{"name":"Programming","slug":"programming","url":"https://listedarticles.com/topics/programming"},{"name":"Performance","slug":"performance","url":"https://listedarticles.com/topics/performance"}],"about_listings":[],"cover_image_url":null,"license":"all-rights-reserved","word_count":3875,"reading_minutes":17,"published_at":"2026-10-07T00:00:00.000Z","added_at":"2026-10-07T14:28:03.979Z","updated_at":"2026-10-07T14:28:03.979Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":true},"profile_url":"https://listedarticles.com/articles/unrolled-code","markdown_url":"https://listedarticles.com/articles/unrolled-code.md","example":false,"citation":"Noteflakes. \"Unrolled Code.\" 7 Oct 2026. https://noteflakes.com/articles/2026-10-07-unrolled-code (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://noteflakes.com/articles/2026-10-07-unrolled-code"},"body_markdown":"# Unrolled Code\n\n### 07·10·2026\n\nThe other day I was looking at a little project called\n[grubby](https://git.btxx.org/grubby/), a minimal static site generator for git\nrepos, written in Ruby. The style is quite interesting. It feels solid and unapologetic:\n\n```\ndef fill_template(template, page_title, root_prefix)\n  template\n    .gsub(\"{{title}}\", escape_html(page_title))\n    .gsub(\"{{root}}\", root_prefix)\n    .gsub(\"{{stylesheet}}\") { STYLESHEET }\n    .gsub(\"{{build_date}}\", BUILD_DATE)\nend\n```\nNothing is particularly optimized, it just uses available tools to do its work:\n\n```\ndef write_page(page_path, page_title, root_prefix = \"\")\n  FileUtils.mkdir_p(File.dirname(page_path))\n  header = fill_template(HEADER_TEMPLATE, page_title, root_prefix)\n  footer = fill_template(FOOTER_TEMPLATE, page_title, root_prefix)\n  File.write(page_path, header + yield + footer)\nend\n```\nAfter running `git ls-tree` and collecting the filenames in the repository, it\ngenerates an HTML page for each file. Looking at the code examples above we can\ndiscern a primitive templating system: there’s `#fill_template` for\nreplacing place-holders in the template with values, there’s a\n`#render_markdown` helper function, there’s the composition of the inner HTML\nwith the header and footer HTML in `#write_page`.\n\nThe header and footer are stored in separate files, but where are the templates for the actual page content? A bit further down, we find them. Here’s an excerpt from the index page template:\n\n```\n...\nwrite_page(File.join(output_dir, \"index.html\"), repo_name) do\n  ...\n  page_html = \"<header>\\n<p><strong>#{escape_html(repo_name)}</strong></p>\\n\"\n  page_html += \"<p>#{escape_html(repo_description)}</p>\\n\"\n  page_html += \"<p><code>#{escape_html(clone_command)}</code></p>\\n</header>\\n\"\n  ...\n  page_html\nend\n...\n```\nThis code has a very specific shape: it’s a series of operations that stuff\nstrings into a buffer. In fact, this code looks very similar to the kind of code\nthat will actually run when you use\n[Papercraft](https://github.com/digital-fabric/papercraft) or\n[ERB](https://github.com/ruby/erb) for generating HTML from templates. Both ERB\nand Papercraft compile the templates into optimized Ruby code that emits\nsnippets of HTML into a buffer.\n\nI find it interesting that the code remains very readable, even though it’s very low level. There are of course many different ways to write this kind of code. We could use a heredoc with string interpolation:\n\n```\npage_html = <<~HTML\n  <header>\\n<p><strong>#{escape_html(repo_name)}</strong></p>\n  <p>#{escape_html(repo_description)}</p>\n  <p><code>#{escape_html(clone_command)}</code></p>\\n</header>\nHTML\n```\nThere’s also the *optimized* way that avoids interpolation and therefore double\ncopying of strings:\n\n```\npage_html <<\n  \"<header>\\n<p><strong>\" << escape_html(repo_name) <<\n  \"</strong></p>\\n<p>\" << escape_html(repo_description) <<\n  \"</p>\\n<p><code>\" << escape_html(clone_command) <<\n  \"</code></p>\\n</header>\\n\"\n```\nA bit less readable, but somewhat faster. Both ERB and Papercraft compile code into this form. Just for kicks, how would a corresponding ERB template look?\n\n```\n<header>\n  <p><strong><%= escape_html(repo_name) %></strong></p>\n  <p><%= escape_html(repo_description) %></p>\n  <p><code><%= escape_html(clone_command) %></code></p>\n</header>\n```\nThis looks pretty nice! It’s just HTML with some interpolated strings in it. And how about Papercraft?\n\n```\nheader {\n  p { strong(repo_name) }\n  p(repo_description)\n  p { code(clone_command) }\n}\n```\nEverything is compressed down to a minimal syntax. But in the end, when you\nrender this template, Papercraft will actually compile it into code that looks a\nlot like [grubby](https://git.btxx.org/grubby/):\n\n```\n__buffer__\n  .<<(\"<header><p><strong>\").<<(ERB::Escape.html_escape((repo_name)))\n  .<<(\"</strong></p><p>\").<<(ERB::Escape.html_escape((repo_description)))\n  .<<(\"</p><p><code>\").<<(ERB::Escape.html_escape((clone_command)))\n  .<<(\"</code></p></header>\")\n```\nSo going back to the grubby code, it was interesting to see this style of\ncoding, which basically “unrolls” the code that would have been generated if a\ntemplating tool like ERB or Papercraft was used. But it also reminded me of\nanother code base I was looking at recently, that of\n[Herb](https://github.com/marcoroth/herb), which is a gem with a set of tools\nfor working with ERB templates. Here’s an excerpt:\n\n```\n# from Herb::Engine#initialize:\n...\n@context = Visitor::Context.new(\n  file_path: properties[:filename],\n  project_path: properties[:project_path],\n  options: context_options(properties),\n  resolver: properties[:resolver],\n  **(properties[:context] || {})\n)\n    \n@bufvar = properties[:bufvar] || properties[:outvar] || \"_buf\"\n@escape = properties.fetch(:escape) { properties.fetch(:escape_html, false) }\n@escapefunc = properties.fetch(:escapefunc, @escape ? \"__herb.h\" : \"::Herb::Engine.h\")\n@attrfunc = properties.fetch(:attrfunc, @escape ? \"__herb.attr\" : \"::Herb::Engine.attr\")\n@jsfunc = properties.fetch(:jsfunc, @escape ? \"__herb.js\" : \"::Herb::Engine.js\")\n@cssfunc = properties.fetch(:cssfunc, @escape ? \"__herb.css\" : \"::Herb::Engine.css\")\n@src = properties[:src] || +\"\"\n@chain_appends = properties[:chain_appends]\n@buffer_on_stack = false\n@parser_options = properties.fetch(:parser_options, default_parser_options).transform_keys(&:to_sym)\n...\n```\nThe entire `Herb::Engine#initialize` method is about 65 LOC! And the individual\nlines themselves tend to stretch to the right edge of your editor window. I ran `cloc`\non the code and was really taken aback:\n\n```\n~/playground/herb $ cloc --exclude-dir test --include-ext rb,rs,c,ts .\n...\ngithub.com/AlDanial/cloc v 2.06  T=2.55 s (359.5 files/s, 66052.1 lines/s)\n-------------------------------------------------------------------------------\nLanguage                     files          blank        comment           code\n-------------------------------------------------------------------------------\nTypeScript                     549          19777           4641          65383\nRuby                           161           6838           3255          20728\nRust                           141           5531            338          20397\nC                               66           4649            148          16809\n-------------------------------------------------------------------------------\nSUM:                           917          36795           8382         123317\n-------------------------------------------------------------------------------\n...\n```\nOK, so the Typescript stuff is probably not relevant to the present discussion, but still, 20KLOC of Ruby, and another 37KLOC of C/Rust extensions. For comparison’s sake, ActiveRecord is about 46KLOC (not including tests). The entire Rails codebase is about 120KLOC of Ruby (again, not including tests). Herb just became the default template renderer in Rails 8.2.\n\nHerb’s template compiler code looks beautiful:\n\n```\ndef generate_output\n  optimized_tokens.each do |type, value, context, escaped|\n    case type\n    when :text\n      @engine.send(:add_text, value)\n    when :code\n      @engine.send(:add_code, value)\n    when :expr, :expr_escaped\n      indicator = indicator_for(type)\n      if context_aware_context?(context)\n        @engine.send(:add_context_aware_expression, indicator, value, context)\n      else\n        @engine.send(:add_expression, indicator, value)\n      end\n    when :expr_block, :expr_block_escaped\n      @engine.send(:add_expression_block, indicator_for(type), value)\n    when :expr_block_end\n      @engine.send(:add_expression_block_end, value, escaped: escaped)\n    when :chain\n      @engine.send(:add_expression_result, value)\n    end\n  end\nend\n```\nThis method is basically a router inside of a loop. it converts data into method calls. Again, this kind of functionality could have been hidden behind a DSL, but here we have the entire logic for this algorithm laid out very explicitly in front of our eyes. Another example:\n\n```\ndef self.js(value)\n  value.to_s.gsub(/[\\\\'\"<>&\\n\\r\\t\\f\\b]/) do |char|\n    case char\n    when \"\\n\" then \"\\\\n\"\n    when \"\\r\" then \"\\\\r\"\n    when \"\\t\" then \"\\\\t\"\n    when \"\\f\" then \"\\\\f\"\n    when \"\\b\" then \"\\\\b\"\n    else\n      \"\\\\x#{char.ord.to_s(16).rjust(2, \"0\")}\"\n    end\n  end\nend\n```\nAnd another:\n\n```\ndef add_code(code)\n  terminate_expression\n  if code.include?(\"=begin\") || code.include?(\"=end\")\n    @src << \"\\n\" << code\n    @src << \"\\n\" unless code.end_with?(\"\\n\")\n  else\n    @src << \" \" unless code.match?(/\\A\\n+\\z/)\n    @src << code\n  if Helpers.comment?(code) || Helpers.heredoc?(code)\n    @src << \"\\n\" unless code[-1] == \"\\n\"\n  else\n    @src << \";\" unless code[-1] == \"\\n\"\n  end\n  @buffer_on_stack = false\nend\n```\nIt’s just logic expressed in the purest way possible. The code that we’re looking into here is charged with transforming an ERB template into a piece of Ruby source code containing an optimized renderer for the given template. The optimized source code is painstakingly put together from little bits and pieces, according to the structure of the template. If we take the same HTML template from the grubby example above, ERB/Herb would have emitted the following code:\n\n```\n# edited for formatting\n_erbout = +''\n_erbout.<< \"  <header>\\n  <p><strong>\".freeze\n_erbout.<<(( escape_html(repo_name) ).to_s); _erbout.<< \"</strong></p>\\n  <p>\".freeze\n_erbout.<<(( escape_html(repo_description) ).to_s); _erbout.<< \"</p>\\n  <p><code>\".freeze\n_erbout.<<(( escape_html(clone_command) ).to_s); _erbout.<< \"</code></p>\\n</header>\\n\".freeze\n_erbout\n```\nNote the similarities: we’re dealing with constructing a string, we’re mostly doing just one type of action, and the action is repeated. This is what unrolled code is about: clarity, discipline, optimization, and grouping like actions together. Let’s take a look at a different project:\n\n```\ndef emit_wildcard_childless_root_code(buffer, root_path)\n  emit_code_line(buffer, '->(path, params) {')\n  if root_path != '/'\n    re = /^#{Regexp.escape(root_path)}(\\/.*)?$/\n    emit_code_line(buffer, \"  return if path !~ #{re.inspect}\")\n  end\n  emit_code_line(buffer, \"  @dynamic_map[#{root_path.inspect}]\")\n  emit_code_line(buffer, '}')\nend\n```\nThis is from [Syntropy](https://github.com/digital-fabric/syntropy), which is\nthe web framework that’s driving this website, and the code excerpt is part of\nits routing tree compiler. The idea is to take a tree-like data structure\ndescribing the apps’s directory structure and files, and compile it into an\noptimized router lambda that can deal with parametric and wildcard routes.\n\nThe resulting router code would look something like the following:\n\n```\n->(path, params) {\n  entry = @static_map[path]; return entry if entry\n  segments = path.split(\"/\")\n  return nil if (segments[1] != \"syntropy\")\n  case (s = segments[2])\n  when \"api\"\n    return @dynamic_map[\"/syntropy/api+\"]\n  when \"mod\"\n    case (s = segments[3])\n    when \"bar\"\n      return @dynamic_map[\"/syntropy/mod/bar\"]\n    end\n  when \"params\"\n    case (s = segments[3])\n    when s\n      params[\"foo\"] = s\n      case (s = segments[4])\n      when nil\n        return @dynamic_map[\"/syntropy/params/[foo]\"]\n      end\n    end\n  end\n  return nil\n}\n```\nLike with ERB/Herb, the Syntropy code generates a complex piece of code by putting together strings containing little bits of Ruby source code. The above method could also have been written as follows:\n\n```\ndef emit_wildcard_childless_root_code(buffer, root_path)\n  re = /^#{Regexp.escape(root_path)}(\\/.*)?$/\n  emit_code_block <<~EOF\n    ->(path, params) {\n      #{ 'return if path !~ #{re.inspect}' if root_path != '/' }\n      @dynamic_map[#{root_path.inspect}]\n    }\n  EOF\nend\n```\nThis is much clearer, but still, the code for generating the conditional return\nin the middle there is a bit hairy. What if we had a DSL for generating Ruby\ncode? In Elixir you can define macros that expand into code with a pair of tools\ncalled quote/unquote. In fact, a lot of Elixir’s language features (even basic\nstuff like `if` and `case`) are implemented using macros. When a macro is used,\nthe macro definition is expanded in place, it’s like *parametric code*. This\nidea, like all good ideas, comes from Lisp, where there’s no distinction between\ndata and code. What if we had that in Ruby?\n\n```\ndef wildcard_childless_root_code(root_path)\n  quote { \n    ->(req) {\n      unquote {\n        if root_path != '/'\n          re = /^#{unquote(Regexp.escape(root_path))}(\\/.*)?$/\n          quote { return if path !~ unquote(re) }\n        else\n          :__nop__\n        end\n      }\n      @dynamic_map[unquote(root_path)]\n    }\n  }\nend\n```\nThe `#quote` method returns the AST of the given block. The `#unquote` method is\nused to inject arbitrary values, or nested ASTs into the quoted code. In this\nexample, we conditionally inject a piece of Ruby code expressed with a nested\n`#quote` block, that interpolates a regular expression. The final call to\n`#unquote` injects the value of `root_path` as a literal into the generated code.\n\nNotice the mechanics of quote/unquote: with `#quote` we’re putting code inside\nquotes (obviously), and with `#unquote` we’re temporarily escaping out of the\nquotes in order to perform some computation and inject the result back into the\nquoted code, it’s very much like string interpolation. The expression passed to\n`#unquote` is evaluated at *compile-time*. This allows us to conditionally\ninclude pieces of code in the template. And since `#unquote` always returns an\nAST (or `:__nop__` for nothing), we can use it to compose ASTs together:\n\n```\ndef compile_html(ast)\n  html_parts = []\n  flusher = -> {\n    return :__nop__ if html_parts.empty?\n    \n    html = html_parts.join; html_parts.clear\n    quote { __buffer__ << unquote(html) }\n  }\n  quote {\n    unquote(transform_template_ast(ast))\n    unquote(flusher.())\n    __buffer__\n  }\nend\ndef transform_template_ast(ast)\n  mutate(ast) { |node, transform|\n    if html_tag?(node)\n      emit_html(node, transform, html_parts, flusher)\n    else\n      [flusher.(), *transform.(node)]\n    end\n  }\nend\n```\nHere’s an attempt to apply the idea of quote/unquote to compiling Papercraft\ntemplates. This method takes the template AST, and returns a mutated AST, where\ntag method calls are translated to strings being emitted to a buffer. But since\nwe want to have the same optimized form of bunching together static strings and\nseparating out the dynamic strings, we introduce some compile-time state (the\n`html_parts` buffer), and a `flusher` closure that generates the actual code\nthat emits static strings to the buffer. This design lets us support recursion\nin `#emit_html`, so we can do stuff like `div { p { a 'Home' } }`, since the\nstate is passed as arguments.\n\n## Some complementary tools\n\nSuppose we have this quote/unquote functionality ready to let us generate code programmatically. We still need a few more tools to be able to create code. Consider the following:\n\n```\ndef memoize(*methods)\n  methods.each do |m|\n    ast = Sirop.to_ast(method(m))\n    memoized = mutate(ast, ast.body => quote {\n      (@memo ||= {})[unquote(m)] = begin; unqoute(ast.body); end\n    })\n    eval(Sirop.to_source(memoized))\n  end\nend\n```\n([Sirop](https://github.com/digital-fabric/sirop) is a little gem I wrote to\nhelp work with Prism ASTs.)\n\n`#mutate` works by creating a copy of the AST, letting you replace any node on\nthe tree with another. In this case, we’re implementing a momoized version of a\nmethod by replacing the method body with a conditional assignment, into which\nwe inject the memo key and the original method body. I think this example\ndemonstrates the strength of this approach, it feels magical!\n\nAnother way to work with `#mutate` is by passing it a block that returns either\nthe original node, or a different node in case of a mutation:\n\n```\nl1 = ->(x) { 42 }\nmutated = mutate(Sirop.to_ast(l1)) { |n|\n  n.is_a?(Prism::IntegerNode) ? quote { 43 } : n\n}))\nl2 = eval(Sirop.to_source(mutated))\nl2.() #=> 43\n```\nWhat about keywords? What if, for example, we wanted to programmatically add a\n`when` clause inside of a `case` statement?\n\n```\nquote {\n  case foo\n    unquote(\n      bar ? quote { when :bar; p 'baz' }\n    )\n  end\n}\n```\nThis is invalid syntax, and while Prism will parse this, the AST would contain a\n`MissingNode`, and will otherwise be deformed. Here’s a solution that doesn’t\nfeel too inelegant:\n\n```\ndef make_case_expr(entry)\n  quote {\n    __.case(unquote(entry[:name])) {\n      quote {\n        unquote entry[:options].map { |o|\n          quote { __.when(unquote(o)) { add_option(unquote(o)) } }\n        }\n        __.else { raise 'Invalid option' }\n      }\n    }\n  }\nend\n```\nThis lets us construct `case` statements programmtically, and we can extend this\nidea to basically any keyword, like `rescue`:\n\n```\ndef make_fatal_lambda(body, *fatal_errors)\n  quote {\n    -> {\n      __.begin {\n        unquote(body)\n        unquote(fatal_errors.map { |t|\n          quote { __.rescue(unquote(t) => e) { puts 'BOOM!'; exit!(42) } }\n        })\n      })\n    }\n  }\nend\nmake_fatal_lambda(quote { 1 / 0 }, ZeroDivisionError).() #=> BOOM!\n```\nI find that a functional approach to coding goes very well when working with\nASTs. We treat ASTs as immutable objects, and if we need to change a node\nanywhere on the AST, we can use `#mutate` which creates a copy with the\nrequisite changes. If we’re generating more complex code, as we do in\nPapercraft, Syntropy, or ERB, we can split the code generation logic into\nmultiple methods, each of which prepares a distinct part of the code, and\nreturns an AST. This allows us to create arbitrarily complex pieces of code by\ncomposing ASTs together. Let’s take a real use case. Here’s the template for an\nActiveRecord migration, used by a Rails generator. Yes, Rails uses ERB to generate\ncode:\n\n```\nclass <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]\n  def change\n    create_table :<%= table_name %><%= render_table_with_dom_id %> do |t|\n<% attributes.each do |attribute| -%>\n<% if attribute.password_digest? -%>\n      t.string :password_digest<%= attribute.inject_options %>\n<% elsif attribute.token? -%>\n      t.string :<%= attribute.name %><%= attribute.inject_options %>\n<% else -%>\n      t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>\n<% end -%>\n<% end -%>\n<% if options[:timestamps] -%>\n      t.timestamps\n<% end -%>\n    end\n  end\nend\n```\nHow would it look with quote/unquote? Let’s find out:\n\n```\nversion = ActiveRecord::Migration.current_version\nquote do\n  __.class(unquote(migration_class_name) < ActiveRecord::Migration[unquote(version)]) {\n    def change\n      create_table unquote(table_name) do |t|\n        unquote attributes.map do |attribute|\n          opts = attribute.inject_options\n          if attribute.password_digest?\n            quote { t.string unquote(:\"password_digest#{opts}\") }\n          elsif attribute.token?\n            quote { t.string unquote(:\"#{attribute.name}#{opts}\") }\n          else\n            # note use of unquote as method name\n            quote { t.send(unquote(attribute.type), unquote(:\"#{opts}\") }\n          end\n        end\n        unquote(\n          options[:timestamps] ? quote { t.timestamps } : :__nop__\n        )\n      end\n    end\n  }\nend\n```\nNot very pretty, I admit, but maybe a little refactoring, splitting the code into distinct parts, would make it better:\n\n```\ndef attribute_ast(attribute)\n  opts = attribute.inject_options\n  if attribute.password_digest?\n    quote { t.string unquote(:\"password_digest#{opts}\") }\n  elsif attribute.token?\n    quote { t.string unquote(:\"#{attribute.name}#{opts}\") }\n  else\n    quote { __.call(t, unquote(attribute.type), unquote(:\"#{opts}\") }\n  end\nend\ndef timestamps_ast(options)\n  options[:timestamps] ? quote { t.timestamps } : :__nop__\nend\nversion = ActiveRecord::Migration.current_version\nquote do\n  __.class(unquote(migration_class_name) < ActiveRecord::Migration[unquote(version)]) {\n    def change\n      create_table unquote(table_name) do |t|\n        unquote attributes.map { attribute_ast(it) }\n        unquote(timestamps_ast(options))\n      end\n    end\n  }\nend\n```\nOh yes this is *much* better, as we can now see the shape of the generated code!\nOne more example, fitting for the title of this article:\n\n```\ndef rewrite_block_param(ast, v) {\n  block_param_name = ast.parameters.parameters.requireds[0].name\n  mutate(ast) { |n, t|\n    if n in Prism::LocalVariableReadNode(name: block_param_name)\n      unquote(v)\n    else\n      n\n    end\n  }\n}\ndef unroll(o, &block)\n  block_ast = Sirop.to_ast(block)\n  o.map { |v| rewrite_block_param(block_ast, v) }\nend\nast = quote {\n  -> {\n    unquote unroll(%w{foo bar baz}) { |v| p v }\n  }\n}\nunrolled_printer = eval(Sirop.to_source(ast))\n```\nHere we use `#mutate` to change the body of a given block such that all\nreferences to the block argument will be replaced with an arbitrary value, such\nthat the actual source code of `unrolled_printer` would be:\n\n```\n-> {\n  p 'foo'\n  p 'bar'\n  p 'baz'\n}\n```\n## Walking the Fine Line of Abstraction\n\nThis morning I was looking at a vibe-coded [port of\nCampfire](https://github.com/tobi/campfire-once-ruby-ractor) from Rails to plain\nRuby (with ractors). This is an interesting project, and I think it demonstrates\npretty well the [performance costs of\nRails](https://static.lutke.dev/KTK6Vb/campfire-ruby-explainer/)’ abstractions.\nWith Rails, we choose developer happiness at the expense of machine happiness.\nBut the results show that Ruby is actually pretty fast. OK, not as fast as Rust,\nbut in some cases faster than Go!\n\nAnd the code itself is interesting - a lot of unrolled code for sure, but generated by an LLM:\n\n```\ndef dispatch(request)\n  ...\n  if (verb == \"GET\" || verb == \"HEAD\") && (file = Assets.file(path))\n    return static(file, request)\n  end\n  return health(request) if path == \"/up\"\n  if path.start_with?(STORAGE_PREFIX)\n    # ActiveStorage controllers; the proxy ones stream (ActionController::Live).\n    return Front.finish_response(request, Storage.call(request, path, query), live: path.include?(\"/proxy/\"))\n  end\n  body = nil\n  if verb == \"POST\" && request.headers[\"content-type\"]&.to_s&.start_with?(FORM)\n    body = (request.body&.join || +\"\").force_encoding(Encoding::UTF_8)\n    if (i = body.index(\"_method=\"))\n      m = body[i + 8, 6].to_s[/\\A[a-z]+/i]\n      verb = m.upcase if m && %w[PATCH PUT DELETE].include?(m.upcase)\n    end\n  elsif verb == \"POST\" && request.headers[\"content-type\"]&.to_s&.start_with?(MULTIPART)\n    # Rails forms with file inputs carry _method as a multipart part.\n    body = (request.body&.join || +\"\").force_encoding(Encoding::BINARY)\n    if (i = body.byteindex(METHOD_PART)) && (j = body.byteindex(\"\\r\\n\\r\\n\", i))\n      m = body.byteslice(j + 4, 6).to_s[/\\A[a-z]+/i]\n      verb = m.upcase if m && %w[PATCH PUT DELETE].include?(m.upcase)\n    end\n    body.force_encoding(Encoding::UTF_8)\n  end\n  ...\nend\n```\nLook at the style. The lines stretch to the right, and the code itself is\ndealing with tiny details, no abstractions here, just pure algorithms (and lots\nof branching!) The `#dispatch` method is about 45 lines long, and could have been\neasily refactored into a few separate methods that each does a single thing.\n\nAn experienced programmer would probably have a blast refactoring this code, there are lots of opportunities in there to make it more readable, more maintainable, even snappier than it already is. This is obviously unrolled code, but other parts of the code base do use metaprogramming. For example, let’s look at the router config code, which may look familiar to a Rails developer:\n\n```\nCampfire::ROUTES = Campfire::Router.new do\n  get \"/\", to: \"WelcomeController#show\", format: false\n  get \"/first_run\", to: \"FirstRunsController#show\"\n  post \"/first_run\", to: \"FirstRunsController#create\"\n  get \"/session/new\", to: \"SessionsController#new\"\n  post \"/session\", to: \"SessionsController#create\"\n  delete \"/session\", to: \"SessionsController#destroy\"\n  get \"/session/transfers/:id\", to: \"Sessions::TransfersController#show\"\n  patch \"/session/transfers/:id\", to: \"Sessions::TransfersController#update\"\n  put \"/session/transfers/:id\", to: \"Sessions::TransfersController#update\"\n  ...\nend\n```\nSo there’s a DSL here, using the builder pattern:\n\n```\nclass Router\n  ...\n  \n  def initialize(&block)\n    @groups = Hash.new { |h, k| h[k] = [] }\n    instance_eval(&block)\n  end\n  %w[GET POST PATCH PUT DELETE].each do |verb|\n    define_method(verb.downcase) do |pattern, to:, defaults: nil, format: true|\n      add(verb, pattern, to, defaults, format)\n    end\n  end\n  ...\nend\n```\nThis is just the syntactic sugar, but it’s the `#add` method that does the work\nof computing and storing the route information:\n\n```\ndef add(verb, pattern, to, defaults, format)\n  controller, action = to.split(\"#\")\n  names = []\n  src = pattern.gsub(%r{:(\\w+)|\\*(\\w+)|\\.|@}) do\n    if $1\n      names << $1\n      \"([^/.]+)\"\n    elsif $2\n      names << $2\n      \"(.+)\"\n    else\n      Regexp.escape($&)\n    end\n  end\n  src << \"(?:\\\\.([a-z0-9]+))?\" if format\n  first = pattern.split(\"/\")[1] || \"\"\n  first = \"\" if first.start_with?(\":\")\n  @groups[first] << Route.new(verb, Regexp.new(\"\\\\A#{src}\\\\z\"), names.freeze,\n    controller, action.to_sym, defaults&.freeze)\nend\n```\nThe actual routing of incoming requests is done in `#recognize`:\n\n```\ndef recognize(verb, path)\n  verb = \"GET\" if verb == \"HEAD\"\n  slash = path.index(\"/\", 1)\n  first = slash ? path[1, slash - 1] : path[1..]\n  dot = first.index(\".\")\n  first = first[0, dot] if dot\n  route_in(@groups[first], verb, path) || route_in(@fallback, verb, path)\nend\n```\nHere we can see that what this routing DSL does (as in many cases) is to convert\ncode into data. All routing configuration is stored in `@groups`, and the work\nof actually routing requests (done in `#recognize`) is all about consulting the\nrouting data. But with quote/unquote we can convert data into code, as we saw\nabove in the Syntropy router example. Here’s the original `#route_in` method:\n\n```\ndef route_in(routes, verb, path)\n  return nil unless routes\n  routes.each do |r|\n    next unless r.verb == verb\n    m = r.regex.match(path) or next\n    params = r.defaults ? r.defaults.dup : {}\n    r.names.each_with_index { |n, i| params[n] = m[i + 1]&.force_encoding(Encoding::UTF_8) }\n    return [r, params, m[r.names.size + 1]]\n  end\n  nil\nend\n```\nSee that loop in there? We can unroll it using quote/unquote:\n\n```\ndef compile_groups\n  @groups = @groups.transform_values { make_route_in_proc(it) }\nend\ndef make_route_in_proc(routes)\n  eval Sirop.to_source quote {\n    ->(verb, path) {\n      unquote routes.map { |r|\n        quote {\n          if (unquote(r.verb) == verb && (m = unquote(r.regex.match(path))))\n            params = unquote(r.defaults ? r.defaults.dup : {})\n            unquote(r.names).each_with_index { |n, i| params[n] = m[i + 1]&.force_encoding(Encoding::UTF_8) }\n            return [routes[unquote(routes.index(r))], params, m[unquote(r.names.size + 1)]]\n          end\n        }\n      }\n    }\n  }\nend\n```\nWith this, we’ve converted each route group to a custom-made piece of code.\nNotice the frequent use of `#unquote` - this allows us to change all references\nto the `r` iterator variable into literal values! And we can do this safely\nbecause the routing configuration is immutable. The only place where we need to\ndo a bit more work is in the `return` statement, where we need to also return a\nreference to the specific route. We do this by calling `routes[]` where the\nsubscript is hard-coded using `#unquote`.\n\n## Taking Ruby Metaprogramming to the Next Level\n\nRuby is famous for its productivity and simplicity, and Ruby programmers have\nwholeheartedly embraced its metaprogramming facilities in the quest for\n*developer happiness*. Tools such as `#eval`, `#instance_eval`, and\n`#define_method` let us create beautiful abstractions that make our code more\nreadable and arguably easier to maintain. All those Rails idioms, they’re\ncatchy, they make the intent clear, it’s almost as if they’ve become part of the\nRuby syntax!\n\nThe quote/unquote mechanism I’m proposing here doesn’t exist yet in Ruby, but if it ever materializes, I think it would open a whole new world of possibilities for Ruby. Such tools will allow us to create better abstractions without paying the associated performance overhead. They might make it possible to express new ideas, new idioms, and new techniques for manipulating Ruby code.\n","body_html":"<h1 id=\"unrolled-code\">Unrolled Code</h1>\n<h3 id=\"07-10-2026\">07·10·2026</h3>\n<p>The other day I was looking at a little project called\n<a href=\"https://git.btxx.org/grubby/\" rel=\"nofollow ugc noopener\">grubby</a>, a minimal static site generator for git\nrepos, written in Ruby. The style is quite interesting. It feels solid and unapologetic:</p>\n<pre><code>def fill_template(template, page_title, root_prefix)\n  template\n    .gsub(&quot;{{title}}&quot;, escape_html(page_title))\n    .gsub(&quot;{{root}}&quot;, root_prefix)\n    .gsub(&quot;{{stylesheet}}&quot;) { STYLESHEET }\n    .gsub(&quot;{{build_date}}&quot;, BUILD_DATE)\nend</code></pre>\n<p>Nothing is particularly optimized, it just uses available tools to do its work:</p>\n<pre><code>def write_page(page_path, page_title, root_prefix = &quot;&quot;)\n  FileUtils.mkdir_p(File.dirname(page_path))\n  header = fill_template(HEADER_TEMPLATE, page_title, root_prefix)\n  footer = fill_template(FOOTER_TEMPLATE, page_title, root_prefix)\n  File.write(page_path, header + yield + footer)\nend</code></pre>\n<p>After running <code>git ls-tree</code> and collecting the filenames in the repository, it\ngenerates an HTML page for each file. Looking at the code examples above we can\ndiscern a primitive templating system: there’s <code>#fill_template</code> for\nreplacing place-holders in the template with values, there’s a\n<code>#render_markdown</code> helper function, there’s the composition of the inner HTML\nwith the header and footer HTML in <code>#write_page</code>.</p>\n<p>The header and footer are stored in separate files, but where are the templates for the actual page content? A bit further down, we find them. Here’s an excerpt from the index page template:</p>\n<pre><code>...\nwrite_page(File.join(output_dir, &quot;index.html&quot;), repo_name) do\n  ...\n  page_html = &quot;&lt;header&gt;\\n&lt;p&gt;&lt;strong&gt;#{escape_html(repo_name)}&lt;/strong&gt;&lt;/p&gt;\\n&quot;\n  page_html += &quot;&lt;p&gt;#{escape_html(repo_description)}&lt;/p&gt;\\n&quot;\n  page_html += &quot;&lt;p&gt;&lt;code&gt;#{escape_html(clone_command)}&lt;/code&gt;&lt;/p&gt;\\n&lt;/header&gt;\\n&quot;\n  ...\n  page_html\nend\n...</code></pre>\n<p>This code has a very specific shape: it’s a series of operations that stuff\nstrings into a buffer. In fact, this code looks very similar to the kind of code\nthat will actually run when you use\n<a href=\"https://github.com/digital-fabric/papercraft\" rel=\"nofollow ugc noopener\">Papercraft</a> or\n<a href=\"https://github.com/ruby/erb\" rel=\"nofollow ugc noopener\">ERB</a> for generating HTML from templates. Both ERB\nand Papercraft compile the templates into optimized Ruby code that emits\nsnippets of HTML into a buffer.</p>\n<p>I find it interesting that the code remains very readable, even though it’s very low level. There are of course many different ways to write this kind of code. We could use a heredoc with string interpolation:</p>\n<pre><code>page_html = &lt;&lt;~HTML\n  &lt;header&gt;\\n&lt;p&gt;&lt;strong&gt;#{escape_html(repo_name)}&lt;/strong&gt;&lt;/p&gt;\n  &lt;p&gt;#{escape_html(repo_description)}&lt;/p&gt;\n  &lt;p&gt;&lt;code&gt;#{escape_html(clone_command)}&lt;/code&gt;&lt;/p&gt;\\n&lt;/header&gt;\nHTML</code></pre>\n<p>There’s also the <em>optimized</em> way that avoids interpolation and therefore double\ncopying of strings:</p>\n<pre><code>page_html &lt;&lt;\n  &quot;&lt;header&gt;\\n&lt;p&gt;&lt;strong&gt;&quot; &lt;&lt; escape_html(repo_name) &lt;&lt;\n  &quot;&lt;/strong&gt;&lt;/p&gt;\\n&lt;p&gt;&quot; &lt;&lt; escape_html(repo_description) &lt;&lt;\n  &quot;&lt;/p&gt;\\n&lt;p&gt;&lt;code&gt;&quot; &lt;&lt; escape_html(clone_command) &lt;&lt;\n  &quot;&lt;/code&gt;&lt;/p&gt;\\n&lt;/header&gt;\\n&quot;</code></pre>\n<p>A bit less readable, but somewhat faster. Both ERB and Papercraft compile code into this form. Just for kicks, how would a corresponding ERB template look?</p>\n<pre><code>&lt;header&gt;\n  &lt;p&gt;&lt;strong&gt;&lt;%= escape_html(repo_name) %&gt;&lt;/strong&gt;&lt;/p&gt;\n  &lt;p&gt;&lt;%= escape_html(repo_description) %&gt;&lt;/p&gt;\n  &lt;p&gt;&lt;code&gt;&lt;%= escape_html(clone_command) %&gt;&lt;/code&gt;&lt;/p&gt;\n&lt;/header&gt;</code></pre>\n<p>This looks pretty nice! It’s just HTML with some interpolated strings in it. And how about Papercraft?</p>\n<pre><code>header {\n  p { strong(repo_name) }\n  p(repo_description)\n  p { code(clone_command) }\n}</code></pre>\n<p>Everything is compressed down to a minimal syntax. But in the end, when you\nrender this template, Papercraft will actually compile it into code that looks a\nlot like <a href=\"https://git.btxx.org/grubby/\" rel=\"nofollow ugc noopener\">grubby</a>:</p>\n<pre><code>__buffer__\n  .&lt;&lt;(&quot;&lt;header&gt;&lt;p&gt;&lt;strong&gt;&quot;).&lt;&lt;(ERB::Escape.html_escape((repo_name)))\n  .&lt;&lt;(&quot;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&quot;).&lt;&lt;(ERB::Escape.html_escape((repo_description)))\n  .&lt;&lt;(&quot;&lt;/p&gt;&lt;p&gt;&lt;code&gt;&quot;).&lt;&lt;(ERB::Escape.html_escape((clone_command)))\n  .&lt;&lt;(&quot;&lt;/code&gt;&lt;/p&gt;&lt;/header&gt;&quot;)</code></pre>\n<p>So going back to the grubby code, it was interesting to see this style of\ncoding, which basically “unrolls” the code that would have been generated if a\ntemplating tool like ERB or Papercraft was used. But it also reminded me of\nanother code base I was looking at recently, that of\n<a href=\"https://github.com/marcoroth/herb\" rel=\"nofollow ugc noopener\">Herb</a>, which is a gem with a set of tools\nfor working with ERB templates. Here’s an excerpt:</p>\n<pre><code># from Herb::Engine#initialize:\n...\n@context = Visitor::Context.new(\n  file_path: properties[:filename],\n  project_path: properties[:project_path],\n  options: context_options(properties),\n  resolver: properties[:resolver],\n  **(properties[:context] || {})\n)\n    \n@bufvar = properties[:bufvar] || properties[:outvar] || &quot;_buf&quot;\n@escape = properties.fetch(:escape) { properties.fetch(:escape_html, false) }\n@escapefunc = properties.fetch(:escapefunc, @escape ? &quot;__herb.h&quot; : &quot;::Herb::Engine.h&quot;)\n@attrfunc = properties.fetch(:attrfunc, @escape ? &quot;__herb.attr&quot; : &quot;::Herb::Engine.attr&quot;)\n@jsfunc = properties.fetch(:jsfunc, @escape ? &quot;__herb.js&quot; : &quot;::Herb::Engine.js&quot;)\n@cssfunc = properties.fetch(:cssfunc, @escape ? &quot;__herb.css&quot; : &quot;::Herb::Engine.css&quot;)\n@src = properties[:src] || +&quot;&quot;\n@chain_appends = properties[:chain_appends]\n@buffer_on_stack = false\n@parser_options = properties.fetch(:parser_options, default_parser_options).transform_keys(&amp;:to_sym)\n...</code></pre>\n<p>The entire <code>Herb::Engine#initialize</code> method is about 65 LOC! And the individual\nlines themselves tend to stretch to the right edge of your editor window. I ran <code>cloc</code>\non the code and was really taken aback:</p>\n<pre><code>~/playground/herb $ cloc --exclude-dir test --include-ext rb,rs,c,ts .\n...\ngithub.com/AlDanial/cloc v 2.06  T=2.55 s (359.5 files/s, 66052.1 lines/s)\n-------------------------------------------------------------------------------\nLanguage                     files          blank        comment           code\n-------------------------------------------------------------------------------\nTypeScript                     549          19777           4641          65383\nRuby                           161           6838           3255          20728\nRust                           141           5531            338          20397\nC                               66           4649            148          16809\n-------------------------------------------------------------------------------\nSUM:                           917          36795           8382         123317\n-------------------------------------------------------------------------------\n...</code></pre>\n<p>OK, so the Typescript stuff is probably not relevant to the present discussion, but still, 20KLOC of Ruby, and another 37KLOC of C/Rust extensions. For comparison’s sake, ActiveRecord is about 46KLOC (not including tests). The entire Rails codebase is about 120KLOC of Ruby (again, not including tests). Herb just became the default template renderer in Rails 8.2.</p>\n<p>Herb’s template compiler code looks beautiful:</p>\n<pre><code>def generate_output\n  optimized_tokens.each do |type, value, context, escaped|\n    case type\n    when :text\n      @engine.send(:add_text, value)\n    when :code\n      @engine.send(:add_code, value)\n    when :expr, :expr_escaped\n      indicator = indicator_for(type)\n      if context_aware_context?(context)\n        @engine.send(:add_context_aware_expression, indicator, value, context)\n      else\n        @engine.send(:add_expression, indicator, value)\n      end\n    when :expr_block, :expr_block_escaped\n      @engine.send(:add_expression_block, indicator_for(type), value)\n    when :expr_block_end\n      @engine.send(:add_expression_block_end, value, escaped: escaped)\n    when :chain\n      @engine.send(:add_expression_result, value)\n    end\n  end\nend</code></pre>\n<p>This method is basically a router inside of a loop. it converts data into method calls. Again, this kind of functionality could have been hidden behind a DSL, but here we have the entire logic for this algorithm laid out very explicitly in front of our eyes. Another example:</p>\n<pre><code>def self.js(value)\n  value.to_s.gsub(/[\\\\&#39;&quot;&lt;&gt;&amp;\\n\\r\\t\\f\\b]/) do |char|\n    case char\n    when &quot;\\n&quot; then &quot;\\\\n&quot;\n    when &quot;\\r&quot; then &quot;\\\\r&quot;\n    when &quot;\\t&quot; then &quot;\\\\t&quot;\n    when &quot;\\f&quot; then &quot;\\\\f&quot;\n    when &quot;\\b&quot; then &quot;\\\\b&quot;\n    else\n      &quot;\\\\x#{char.ord.to_s(16).rjust(2, &quot;0&quot;)}&quot;\n    end\n  end\nend</code></pre>\n<p>And another:</p>\n<pre><code>def add_code(code)\n  terminate_expression\n  if code.include?(&quot;=begin&quot;) || code.include?(&quot;=end&quot;)\n    @src &lt;&lt; &quot;\\n&quot; &lt;&lt; code\n    @src &lt;&lt; &quot;\\n&quot; unless code.end_with?(&quot;\\n&quot;)\n  else\n    @src &lt;&lt; &quot; &quot; unless code.match?(/\\A\\n+\\z/)\n    @src &lt;&lt; code\n  if Helpers.comment?(code) || Helpers.heredoc?(code)\n    @src &lt;&lt; &quot;\\n&quot; unless code[-1] == &quot;\\n&quot;\n  else\n    @src &lt;&lt; &quot;;&quot; unless code[-1] == &quot;\\n&quot;\n  end\n  @buffer_on_stack = false\nend</code></pre>\n<p>It’s just logic expressed in the purest way possible. The code that we’re looking into here is charged with transforming an ERB template into a piece of Ruby source code containing an optimized renderer for the given template. The optimized source code is painstakingly put together from little bits and pieces, according to the structure of the template. If we take the same HTML template from the grubby example above, ERB/Herb would have emitted the following code:</p>\n<pre><code># edited for formatting\n_erbout = +&#39;&#39;\n_erbout.&lt;&lt; &quot;  &lt;header&gt;\\n  &lt;p&gt;&lt;strong&gt;&quot;.freeze\n_erbout.&lt;&lt;(( escape_html(repo_name) ).to_s); _erbout.&lt;&lt; &quot;&lt;/strong&gt;&lt;/p&gt;\\n  &lt;p&gt;&quot;.freeze\n_erbout.&lt;&lt;(( escape_html(repo_description) ).to_s); _erbout.&lt;&lt; &quot;&lt;/p&gt;\\n  &lt;p&gt;&lt;code&gt;&quot;.freeze\n_erbout.&lt;&lt;(( escape_html(clone_command) ).to_s); _erbout.&lt;&lt; &quot;&lt;/code&gt;&lt;/p&gt;\\n&lt;/header&gt;\\n&quot;.freeze\n_erbout</code></pre>\n<p>Note the similarities: we’re dealing with constructing a string, we’re mostly doing just one type of action, and the action is repeated. This is what unrolled code is about: clarity, discipline, optimization, and grouping like actions together. Let’s take a look at a different project:</p>\n<pre><code>def emit_wildcard_childless_root_code(buffer, root_path)\n  emit_code_line(buffer, &#39;-&gt;(path, params) {&#39;)\n  if root_path != &#39;/&#39;\n    re = /^#{Regexp.escape(root_path)}(\\/.*)?$/\n    emit_code_line(buffer, &quot;  return if path !~ #{re.inspect}&quot;)\n  end\n  emit_code_line(buffer, &quot;  @dynamic_map[#{root_path.inspect}]&quot;)\n  emit_code_line(buffer, &#39;}&#39;)\nend</code></pre>\n<p>This is from <a href=\"https://github.com/digital-fabric/syntropy\" rel=\"nofollow ugc noopener\">Syntropy</a>, which is\nthe web framework that’s driving this website, and the code excerpt is part of\nits routing tree compiler. The idea is to take a tree-like data structure\ndescribing the apps’s directory structure and files, and compile it into an\noptimized router lambda that can deal with parametric and wildcard routes.</p>\n<p>The resulting router code would look something like the following:</p>\n<pre><code>-&gt;(path, params) {\n  entry = @static_map[path]; return entry if entry\n  segments = path.split(&quot;/&quot;)\n  return nil if (segments[1] != &quot;syntropy&quot;)\n  case (s = segments[2])\n  when &quot;api&quot;\n    return @dynamic_map[&quot;/syntropy/api+&quot;]\n  when &quot;mod&quot;\n    case (s = segments[3])\n    when &quot;bar&quot;\n      return @dynamic_map[&quot;/syntropy/mod/bar&quot;]\n    end\n  when &quot;params&quot;\n    case (s = segments[3])\n    when s\n      params[&quot;foo&quot;] = s\n      case (s = segments[4])\n      when nil\n        return @dynamic_map[&quot;/syntropy/params/[foo]&quot;]\n      end\n    end\n  end\n  return nil\n}</code></pre>\n<p>Like with ERB/Herb, the Syntropy code generates a complex piece of code by putting together strings containing little bits of Ruby source code. The above method could also have been written as follows:</p>\n<pre><code>def emit_wildcard_childless_root_code(buffer, root_path)\n  re = /^#{Regexp.escape(root_path)}(\\/.*)?$/\n  emit_code_block &lt;&lt;~EOF\n    -&gt;(path, params) {\n      #{ &#39;return if path !~ #{re.inspect}&#39; if root_path != &#39;/&#39; }\n      @dynamic_map[#{root_path.inspect}]\n    }\n  EOF\nend</code></pre>\n<p>This is much clearer, but still, the code for generating the conditional return\nin the middle there is a bit hairy. What if we had a DSL for generating Ruby\ncode? In Elixir you can define macros that expand into code with a pair of tools\ncalled quote/unquote. In fact, a lot of Elixir’s language features (even basic\nstuff like <code>if</code> and <code>case</code>) are implemented using macros. When a macro is used,\nthe macro definition is expanded in place, it’s like <em>parametric code</em>. This\nidea, like all good ideas, comes from Lisp, where there’s no distinction between\ndata and code. What if we had that in Ruby?</p>\n<pre><code>def wildcard_childless_root_code(root_path)\n  quote { \n    -&gt;(req) {\n      unquote {\n        if root_path != &#39;/&#39;\n          re = /^#{unquote(Regexp.escape(root_path))}(\\/.*)?$/\n          quote { return if path !~ unquote(re) }\n        else\n          :__nop__\n        end\n      }\n      @dynamic_map[unquote(root_path)]\n    }\n  }\nend</code></pre>\n<p>The <code>#quote</code> method returns the AST of the given block. The <code>#unquote</code> method is\nused to inject arbitrary values, or nested ASTs into the quoted code. In this\nexample, we conditionally inject a piece of Ruby code expressed with a nested\n<code>#quote</code> block, that interpolates a regular expression. The final call to\n<code>#unquote</code> injects the value of <code>root_path</code> as a literal into the generated code.</p>\n<p>Notice the mechanics of quote/unquote: with <code>#quote</code> we’re putting code inside\nquotes (obviously), and with <code>#unquote</code> we’re temporarily escaping out of the\nquotes in order to perform some computation and inject the result back into the\nquoted code, it’s very much like string interpolation. The expression passed to\n<code>#unquote</code> is evaluated at <em>compile-time</em>. This allows us to conditionally\ninclude pieces of code in the template. And since <code>#unquote</code> always returns an\nAST (or <code>:__nop__</code> for nothing), we can use it to compose ASTs together:</p>\n<pre><code>def compile_html(ast)\n  html_parts = []\n  flusher = -&gt; {\n    return :__nop__ if html_parts.empty?\n    \n    html = html_parts.join; html_parts.clear\n    quote { __buffer__ &lt;&lt; unquote(html) }\n  }\n  quote {\n    unquote(transform_template_ast(ast))\n    unquote(flusher.())\n    __buffer__\n  }\nend\ndef transform_template_ast(ast)\n  mutate(ast) { |node, transform|\n    if html_tag?(node)\n      emit_html(node, transform, html_parts, flusher)\n    else\n      [flusher.(), *transform.(node)]\n    end\n  }\nend</code></pre>\n<p>Here’s an attempt to apply the idea of quote/unquote to compiling Papercraft\ntemplates. This method takes the template AST, and returns a mutated AST, where\ntag method calls are translated to strings being emitted to a buffer. But since\nwe want to have the same optimized form of bunching together static strings and\nseparating out the dynamic strings, we introduce some compile-time state (the\n<code>html_parts</code> buffer), and a <code>flusher</code> closure that generates the actual code\nthat emits static strings to the buffer. This design lets us support recursion\nin <code>#emit_html</code>, so we can do stuff like <code>div { p { a &#39;Home&#39; } }</code>, since the\nstate is passed as arguments.</p>\n<h2 id=\"some-complementary-tools\">Some complementary tools</h2>\n<p>Suppose we have this quote/unquote functionality ready to let us generate code programmatically. We still need a few more tools to be able to create code. Consider the following:</p>\n<pre><code>def memoize(*methods)\n  methods.each do |m|\n    ast = Sirop.to_ast(method(m))\n    memoized = mutate(ast, ast.body =&gt; quote {\n      (@memo ||= {})[unquote(m)] = begin; unqoute(ast.body); end\n    })\n    eval(Sirop.to_source(memoized))\n  end\nend</code></pre>\n<p>(<a href=\"https://github.com/digital-fabric/sirop\" rel=\"nofollow ugc noopener\">Sirop</a> is a little gem I wrote to\nhelp work with Prism ASTs.)</p>\n<p><code>#mutate</code> works by creating a copy of the AST, letting you replace any node on\nthe tree with another. In this case, we’re implementing a momoized version of a\nmethod by replacing the method body with a conditional assignment, into which\nwe inject the memo key and the original method body. I think this example\ndemonstrates the strength of this approach, it feels magical!</p>\n<p>Another way to work with <code>#mutate</code> is by passing it a block that returns either\nthe original node, or a different node in case of a mutation:</p>\n<pre><code>l1 = -&gt;(x) { 42 }\nmutated = mutate(Sirop.to_ast(l1)) { |n|\n  n.is_a?(Prism::IntegerNode) ? quote { 43 } : n\n}))\nl2 = eval(Sirop.to_source(mutated))\nl2.() #=&gt; 43</code></pre>\n<p>What about keywords? What if, for example, we wanted to programmatically add a\n<code>when</code> clause inside of a <code>case</code> statement?</p>\n<pre><code>quote {\n  case foo\n    unquote(\n      bar ? quote { when :bar; p &#39;baz&#39; }\n    )\n  end\n}</code></pre>\n<p>This is invalid syntax, and while Prism will parse this, the AST would contain a\n<code>MissingNode</code>, and will otherwise be deformed. Here’s a solution that doesn’t\nfeel too inelegant:</p>\n<pre><code>def make_case_expr(entry)\n  quote {\n    __.case(unquote(entry[:name])) {\n      quote {\n        unquote entry[:options].map { |o|\n          quote { __.when(unquote(o)) { add_option(unquote(o)) } }\n        }\n        __.else { raise &#39;Invalid option&#39; }\n      }\n    }\n  }\nend</code></pre>\n<p>This lets us construct <code>case</code> statements programmtically, and we can extend this\nidea to basically any keyword, like <code>rescue</code>:</p>\n<pre><code>def make_fatal_lambda(body, *fatal_errors)\n  quote {\n    -&gt; {\n      __.begin {\n        unquote(body)\n        unquote(fatal_errors.map { |t|\n          quote { __.rescue(unquote(t) =&gt; e) { puts &#39;BOOM!&#39;; exit!(42) } }\n        })\n      })\n    }\n  }\nend\nmake_fatal_lambda(quote { 1 / 0 }, ZeroDivisionError).() #=&gt; BOOM!</code></pre>\n<p>I find that a functional approach to coding goes very well when working with\nASTs. We treat ASTs as immutable objects, and if we need to change a node\nanywhere on the AST, we can use <code>#mutate</code> which creates a copy with the\nrequisite changes. If we’re generating more complex code, as we do in\nPapercraft, Syntropy, or ERB, we can split the code generation logic into\nmultiple methods, each of which prepares a distinct part of the code, and\nreturns an AST. This allows us to create arbitrarily complex pieces of code by\ncomposing ASTs together. Let’s take a real use case. Here’s the template for an\nActiveRecord migration, used by a Rails generator. Yes, Rails uses ERB to generate\ncode:</p>\n<pre><code>class &lt;%= migration_class_name %&gt; &lt; ActiveRecord::Migration[&lt;%= ActiveRecord::Migration.current_version %&gt;]\n  def change\n    create_table :&lt;%= table_name %&gt;&lt;%= render_table_with_dom_id %&gt; do |t|\n&lt;% attributes.each do |attribute| -%&gt;\n&lt;% if attribute.password_digest? -%&gt;\n      t.string :password_digest&lt;%= attribute.inject_options %&gt;\n&lt;% elsif attribute.token? -%&gt;\n      t.string :&lt;%= attribute.name %&gt;&lt;%= attribute.inject_options %&gt;\n&lt;% else -%&gt;\n      t.&lt;%= attribute.type %&gt; :&lt;%= attribute.name %&gt;&lt;%= attribute.inject_options %&gt;\n&lt;% end -%&gt;\n&lt;% end -%&gt;\n&lt;% if options[:timestamps] -%&gt;\n      t.timestamps\n&lt;% end -%&gt;\n    end\n  end\nend</code></pre>\n<p>How would it look with quote/unquote? Let’s find out:</p>\n<pre><code>version = ActiveRecord::Migration.current_version\nquote do\n  __.class(unquote(migration_class_name) &lt; ActiveRecord::Migration[unquote(version)]) {\n    def change\n      create_table unquote(table_name) do |t|\n        unquote attributes.map do |attribute|\n          opts = attribute.inject_options\n          if attribute.password_digest?\n            quote { t.string unquote(:&quot;password_digest#{opts}&quot;) }\n          elsif attribute.token?\n            quote { t.string unquote(:&quot;#{attribute.name}#{opts}&quot;) }\n          else\n            # note use of unquote as method name\n            quote { t.send(unquote(attribute.type), unquote(:&quot;#{opts}&quot;) }\n          end\n        end\n        unquote(\n          options[:timestamps] ? quote { t.timestamps } : :__nop__\n        )\n      end\n    end\n  }\nend</code></pre>\n<p>Not very pretty, I admit, but maybe a little refactoring, splitting the code into distinct parts, would make it better:</p>\n<pre><code>def attribute_ast(attribute)\n  opts = attribute.inject_options\n  if attribute.password_digest?\n    quote { t.string unquote(:&quot;password_digest#{opts}&quot;) }\n  elsif attribute.token?\n    quote { t.string unquote(:&quot;#{attribute.name}#{opts}&quot;) }\n  else\n    quote { __.call(t, unquote(attribute.type), unquote(:&quot;#{opts}&quot;) }\n  end\nend\ndef timestamps_ast(options)\n  options[:timestamps] ? quote { t.timestamps } : :__nop__\nend\nversion = ActiveRecord::Migration.current_version\nquote do\n  __.class(unquote(migration_class_name) &lt; ActiveRecord::Migration[unquote(version)]) {\n    def change\n      create_table unquote(table_name) do |t|\n        unquote attributes.map { attribute_ast(it) }\n        unquote(timestamps_ast(options))\n      end\n    end\n  }\nend</code></pre>\n<p>Oh yes this is <em>much</em> better, as we can now see the shape of the generated code!\nOne more example, fitting for the title of this article:</p>\n<pre><code>def rewrite_block_param(ast, v) {\n  block_param_name = ast.parameters.parameters.requireds[0].name\n  mutate(ast) { |n, t|\n    if n in Prism::LocalVariableReadNode(name: block_param_name)\n      unquote(v)\n    else\n      n\n    end\n  }\n}\ndef unroll(o, &amp;block)\n  block_ast = Sirop.to_ast(block)\n  o.map { |v| rewrite_block_param(block_ast, v) }\nend\nast = quote {\n  -&gt; {\n    unquote unroll(%w{foo bar baz}) { |v| p v }\n  }\n}\nunrolled_printer = eval(Sirop.to_source(ast))</code></pre>\n<p>Here we use <code>#mutate</code> to change the body of a given block such that all\nreferences to the block argument will be replaced with an arbitrary value, such\nthat the actual source code of <code>unrolled_printer</code> would be:</p>\n<pre><code>-&gt; {\n  p &#39;foo&#39;\n  p &#39;bar&#39;\n  p &#39;baz&#39;\n}</code></pre>\n<h2 id=\"walking-the-fine-line-of-abstraction\">Walking the Fine Line of Abstraction</h2>\n<p>This morning I was looking at a vibe-coded <a href=\"https://github.com/tobi/campfire-once-ruby-ractor\" rel=\"nofollow ugc noopener\">port of\nCampfire</a> from Rails to plain\nRuby (with ractors). This is an interesting project, and I think it demonstrates\npretty well the <a href=\"https://static.lutke.dev/KTK6Vb/campfire-ruby-explainer/\" rel=\"nofollow ugc noopener\">performance costs of\nRails</a>’ abstractions.\nWith Rails, we choose developer happiness at the expense of machine happiness.\nBut the results show that Ruby is actually pretty fast. OK, not as fast as Rust,\nbut in some cases faster than Go!</p>\n<p>And the code itself is interesting - a lot of unrolled code for sure, but generated by an LLM:</p>\n<pre><code>def dispatch(request)\n  ...\n  if (verb == &quot;GET&quot; || verb == &quot;HEAD&quot;) &amp;&amp; (file = Assets.file(path))\n    return static(file, request)\n  end\n  return health(request) if path == &quot;/up&quot;\n  if path.start_with?(STORAGE_PREFIX)\n    # ActiveStorage controllers; the proxy ones stream (ActionController::Live).\n    return Front.finish_response(request, Storage.call(request, path, query), live: path.include?(&quot;/proxy/&quot;))\n  end\n  body = nil\n  if verb == &quot;POST&quot; &amp;&amp; request.headers[&quot;content-type&quot;]&amp;.to_s&amp;.start_with?(FORM)\n    body = (request.body&amp;.join || +&quot;&quot;).force_encoding(Encoding::UTF_8)\n    if (i = body.index(&quot;_method=&quot;))\n      m = body[i + 8, 6].to_s[/\\A[a-z]+/i]\n      verb = m.upcase if m &amp;&amp; %w[PATCH PUT DELETE].include?(m.upcase)\n    end\n  elsif verb == &quot;POST&quot; &amp;&amp; request.headers[&quot;content-type&quot;]&amp;.to_s&amp;.start_with?(MULTIPART)\n    # Rails forms with file inputs carry _method as a multipart part.\n    body = (request.body&amp;.join || +&quot;&quot;).force_encoding(Encoding::BINARY)\n    if (i = body.byteindex(METHOD_PART)) &amp;&amp; (j = body.byteindex(&quot;\\r\\n\\r\\n&quot;, i))\n      m = body.byteslice(j + 4, 6).to_s[/\\A[a-z]+/i]\n      verb = m.upcase if m &amp;&amp; %w[PATCH PUT DELETE].include?(m.upcase)\n    end\n    body.force_encoding(Encoding::UTF_8)\n  end\n  ...\nend</code></pre>\n<p>Look at the style. The lines stretch to the right, and the code itself is\ndealing with tiny details, no abstractions here, just pure algorithms (and lots\nof branching!) The <code>#dispatch</code> method is about 45 lines long, and could have been\neasily refactored into a few separate methods that each does a single thing.</p>\n<p>An experienced programmer would probably have a blast refactoring this code, there are lots of opportunities in there to make it more readable, more maintainable, even snappier than it already is. This is obviously unrolled code, but other parts of the code base do use metaprogramming. For example, let’s look at the router config code, which may look familiar to a Rails developer:</p>\n<pre><code>Campfire::ROUTES = Campfire::Router.new do\n  get &quot;/&quot;, to: &quot;WelcomeController#show&quot;, format: false\n  get &quot;/first_run&quot;, to: &quot;FirstRunsController#show&quot;\n  post &quot;/first_run&quot;, to: &quot;FirstRunsController#create&quot;\n  get &quot;/session/new&quot;, to: &quot;SessionsController#new&quot;\n  post &quot;/session&quot;, to: &quot;SessionsController#create&quot;\n  delete &quot;/session&quot;, to: &quot;SessionsController#destroy&quot;\n  get &quot;/session/transfers/:id&quot;, to: &quot;Sessions::TransfersController#show&quot;\n  patch &quot;/session/transfers/:id&quot;, to: &quot;Sessions::TransfersController#update&quot;\n  put &quot;/session/transfers/:id&quot;, to: &quot;Sessions::TransfersController#update&quot;\n  ...\nend</code></pre>\n<p>So there’s a DSL here, using the builder pattern:</p>\n<pre><code>class Router\n  ...\n  \n  def initialize(&amp;block)\n    @groups = Hash.new { |h, k| h[k] = [] }\n    instance_eval(&amp;block)\n  end\n  %w[GET POST PATCH PUT DELETE].each do |verb|\n    define_method(verb.downcase) do |pattern, to:, defaults: nil, format: true|\n      add(verb, pattern, to, defaults, format)\n    end\n  end\n  ...\nend</code></pre>\n<p>This is just the syntactic sugar, but it’s the <code>#add</code> method that does the work\nof computing and storing the route information:</p>\n<pre><code>def add(verb, pattern, to, defaults, format)\n  controller, action = to.split(&quot;#&quot;)\n  names = []\n  src = pattern.gsub(%r{:(\\w+)|\\*(\\w+)|\\.|@}) do\n    if $1\n      names &lt;&lt; $1\n      &quot;([^/.]+)&quot;\n    elsif $2\n      names &lt;&lt; $2\n      &quot;(.+)&quot;\n    else\n      Regexp.escape($&amp;)\n    end\n  end\n  src &lt;&lt; &quot;(?:\\\\.([a-z0-9]+))?&quot; if format\n  first = pattern.split(&quot;/&quot;)[1] || &quot;&quot;\n  first = &quot;&quot; if first.start_with?(&quot;:&quot;)\n  @groups[first] &lt;&lt; Route.new(verb, Regexp.new(&quot;\\\\A#{src}\\\\z&quot;), names.freeze,\n    controller, action.to_sym, defaults&amp;.freeze)\nend</code></pre>\n<p>The actual routing of incoming requests is done in <code>#recognize</code>:</p>\n<pre><code>def recognize(verb, path)\n  verb = &quot;GET&quot; if verb == &quot;HEAD&quot;\n  slash = path.index(&quot;/&quot;, 1)\n  first = slash ? path[1, slash - 1] : path[1..]\n  dot = first.index(&quot;.&quot;)\n  first = first[0, dot] if dot\n  route_in(@groups[first], verb, path) || route_in(@fallback, verb, path)\nend</code></pre>\n<p>Here we can see that what this routing DSL does (as in many cases) is to convert\ncode into data. All routing configuration is stored in <code>@groups</code>, and the work\nof actually routing requests (done in <code>#recognize</code>) is all about consulting the\nrouting data. But with quote/unquote we can convert data into code, as we saw\nabove in the Syntropy router example. Here’s the original <code>#route_in</code> method:</p>\n<pre><code>def route_in(routes, verb, path)\n  return nil unless routes\n  routes.each do |r|\n    next unless r.verb == verb\n    m = r.regex.match(path) or next\n    params = r.defaults ? r.defaults.dup : {}\n    r.names.each_with_index { |n, i| params[n] = m[i + 1]&amp;.force_encoding(Encoding::UTF_8) }\n    return [r, params, m[r.names.size + 1]]\n  end\n  nil\nend</code></pre>\n<p>See that loop in there? We can unroll it using quote/unquote:</p>\n<pre><code>def compile_groups\n  @groups = @groups.transform_values { make_route_in_proc(it) }\nend\ndef make_route_in_proc(routes)\n  eval Sirop.to_source quote {\n    -&gt;(verb, path) {\n      unquote routes.map { |r|\n        quote {\n          if (unquote(r.verb) == verb &amp;&amp; (m = unquote(r.regex.match(path))))\n            params = unquote(r.defaults ? r.defaults.dup : {})\n            unquote(r.names).each_with_index { |n, i| params[n] = m[i + 1]&amp;.force_encoding(Encoding::UTF_8) }\n            return [routes[unquote(routes.index(r))], params, m[unquote(r.names.size + 1)]]\n          end\n        }\n      }\n    }\n  }\nend</code></pre>\n<p>With this, we’ve converted each route group to a custom-made piece of code.\nNotice the frequent use of <code>#unquote</code> - this allows us to change all references\nto the <code>r</code> iterator variable into literal values! And we can do this safely\nbecause the routing configuration is immutable. The only place where we need to\ndo a bit more work is in the <code>return</code> statement, where we need to also return a\nreference to the specific route. We do this by calling <code>routes[]</code> where the\nsubscript is hard-coded using <code>#unquote</code>.</p>\n<h2 id=\"taking-ruby-metaprogramming-to-the-next-level\">Taking Ruby Metaprogramming to the Next Level</h2>\n<p>Ruby is famous for its productivity and simplicity, and Ruby programmers have\nwholeheartedly embraced its metaprogramming facilities in the quest for\n<em>developer happiness</em>. Tools such as <code>#eval</code>, <code>#instance_eval</code>, and\n<code>#define_method</code> let us create beautiful abstractions that make our code more\nreadable and arguably easier to maintain. All those Rails idioms, they’re\ncatchy, they make the intent clear, it’s almost as if they’ve become part of the\nRuby syntax!</p>\n<p>The quote/unquote mechanism I’m proposing here doesn’t exist yet in Ruby, but if it ever materializes, I think it would open a whole new world of possibilities for Ruby. Such tools will allow us to create better abstractions without paying the associated performance overhead. They might make it possible to express new ideas, new idioms, and new techniques for manipulating Ruby code.</p>","headings":[{"level":1,"text":"Unrolled Code","id":"unrolled-code"},{"level":3,"text":"07·10·2026","id":"07-10-2026"},{"level":2,"text":"Some complementary tools","id":"some-complementary-tools"},{"level":2,"text":"Walking the Fine Line of Abstraction","id":"walking-the-fine-line-of-abstraction"},{"level":2,"text":"Taking Ruby Metaprogramming to the Next Level","id":"taking-ruby-metaprogramming-to-the-next-level"}]}}