Skip to content

Cross-language parity

The same logic, written in any of them, gets the same score:

Terminal window
// frontend/orders.ts
for (const order of orders) { // +1
if (order.isActive()) { // +2
order.items().map((item) => { // +0, nesting 3
if (item.qty > 0) { // +4
return item.qty > 10 ? 'bulk' : 'single' // +5
Terminal window
# services/orders.py
for order in orders: # +1
if order.is_active(): # +2
def label(item): # +0, nesting 3
if item.qty > 0: # +4
return "bulk" if item.qty > 10 else "single" # +5
Terminal window
// services/OrderRepository.java
for (Order order : orders) { // +1
if (order.isActive()) { // +2
order.items().stream().map(item -> { // +0, nesting 3
if (item.qty > 0) { // +4
return item.qty > 10 ? "bulk" : "single"; // +5
Terminal window
// backend/Orders.php
foreach ($orders as $order) { // +1
if ($order->isActive()) { // +2
array_map(function ($item) { // +0, nesting 3
if ($item->qty > 0) { // +4
return $item->qty > 10 ? 'bulk' : 'single'; // +5
Terminal window
// services/orders.go
for _, order := range orders { // +1
if order.IsActive() { // +2
lo.Map(order.Items(), func(item Item, _ int) string { // +0, nesting 3
if item.Qty > 0 { // +4
if item.Qty > 10 { // +5

A Python lambda cannot hold an if statement, so its callback is a nested def, which nests exactly as the lambda would. Go has no conditional expression, so its last decision is an if. That costs the same +1 plus nesting as the ternary does. The Java key carries the parameter types, because Java overloads methods by them.

Terminal window
12 backend/Orders.php:3 OrderRepository::syncLineItems
12 frontend/orders.ts:1 syncLineItems
12 services/OrderRepository.java:3 OrderRepository::syncLineItems(List)
12 services/orders.go:3 OrderRepository::SyncLineItems
12 services/orders.py:3 OrderRepository::sync_line_items

That is what makes one threshold meaningful across a monorepo: a limit of 15 means the same thing to every team in it, whatever language that team writes.

There is only one implementation of the scoring rules. The scorer walks a parsed tree and has no idea which language it is looking at. A language contributes a specification: a plain value naming which node kinds count as a branch, a loop or a closure, plus a few hooks that read its tree, such as where a function’s name comes from. It contributes no scoring code of its own.

So the languages cannot drift apart by accident, because there is nothing to drift: adding Python, Java and Go added no scorer for any of them.

Parity is covered by tests that run on every commit. One compares JavaScript, Python, Java, PHP and Go end to end through the binary; another compares a Vue script block against the equivalent TypeScript file. They pin the exact scores, not merely that the languages agree, so a change that shifted all of them together would still fail.

It is about scores, not syntax. Constructs that exist in one language and not the other are covered by the scoring rules, and a few are deliberate divergences from the reference JavaScript analyser. Parity says that logic expressible in both gets the same number, not that every language has every construct.