What does a platform pay to keep type arguments observable at run time instead of discarding them?
answer
- somebody has to store the argument
- metadata per distinct instantiation
- a runtime that knows about parameters
- an extra value forwarded at every call
- checking is not what is being traded
basics
~20 sKeeping the arguments forces the run-time system to model parameterization: metadata stored for each distinct instantiation, a larger and more complex runtime that understands it, and per-operation work to carry, forward and compare that metadata.
solid answer
~40 sThe argument has to exist somewhere while the program runs, and every implementation of that pays in three currencies. First, **representation**: each distinct instantiation needs a descriptor, and values, containers or call frames must reference it. Second, **runtime complexity**: the run-time system can no longer treat every instantiation as one shape, so its type model, its linking and its tooling all grow - and on an existing platform that is the component hardest to change. Third, **per-operation work**: an argument that must be forwarded into nested generic calls or compared against a value is work the discarding platform simply does not do. What that buys is real - code can act on the argument without evidence being threaded through by hand - but it is bought, not free.
code
pseudocode · 12 linesfunction makeBuffer<T>(count)
// the body has to know T to allocate and to test values
// what the programmer writes
makeBuffer<Shift>(10)
// on a platform that keeps the argument, what actually runs
makeBuffer(descriptorFor(Shift), 10)
// and a generic routine calling another must forward it:
function fillRoster<T>(count)
return makeBuffer(descriptorFor(T), count)go deeper
The thing to hold on to is that an argument which survives has to be stored somewhere and reachable by the running code. Storage and reachability are never free.
Be able to name the three buckets - per-instantiation metadata, a run-time system that must model parameterization, and per-operation work to forward and compare it - rather than answering with a vague 'it is slower'.
Show you can price it against a real workload: where descriptors accumulate, which call paths forward them, and what library authors on a discarding platform pay instead by threading evidence through their signatures.
The lead's angle is who is charged. A fresh platform pays once, at design time; a platform with artifacts in the field would charge every user a rebuild, and that asymmetry decides the design more often than performance does.
## What keeping actually requires Saying a platform keeps type arguments at run time is saying that somewhere in the running program there is a value standing for the argument, and that the code can reach it. That is a stronger claim than it sounds. It means the run-time system has to have a notion of *a parameterized thing*, distinct from the shape that would be left if the argument were dropped, and it has to keep that notion consistent through allocation, linking, inspection and every call that forwards a parameter onward. ## Three places the bill lands 1. **Representation - metadata per instantiation.** Each distinct argument the program uses produces a distinct descriptor: the run-time entity that says *this container holds shifts* rather than *this container holds something*. Values, containers or frames must reference it. A program that parameterizes over dozens of element types now carries dozens of descriptors that the discarding platform never created, and they must be produced, stored and, where a platform allows arguments computed at run time, produced on demand. 2. **Runtime complexity - a bigger thing to build and to keep correct.** Parameterization stops being a compiler-only feature. The run-time system's type model, its identity and equality rules for parameterized entities, its linking, its inspection surface and everything that reads it must all understand the new concept. On a platform that already shipped without it, this is the expensive half, and it is why the decision is usually made once, at the beginning. 3. **Per-operation work - the cost that scales with the program.** An argument that survives has to be passed along. A generic routine that calls another generic routine forwards its argument; an operation that has to decide whether a value matches compares against the descriptor. Individually these are small; on a hot path through parameterized containers, they are the difference the discarding platform banked. ## Two implementation families, one bill - **Carry evidence.** One compiled body, plus the argument handed in as an extra value at the call. Keeps the artifact small, pays at every call and in every forwarding step. - **Generate per instantiation.** A body produced for each argument, with the argument baked in so nothing needs carrying. What that generation costs in artifact size and buys in speed is a separate subject with its own trade; the point here is only that it is the other way to make the argument survive. A candidate who thinks keeping arguments *requires* one body per instantiation, or that discarding is *required* for a single shared body, has collapsed these two axes into one. ## What the bill buys | Capability | Discarding platform | Keeping platform | |---|---|---| | Code acts on the argument while running | needs evidence passed in by hand | reads it directly | | Guarantee at a boundary the compiler did not see | none | can be re-established | | Distinguishing two instantiations at run time | impossible - they are one shape | possible, they are distinct | | Artifact size | flat in the number of arguments used | grows with instantiations or with carried evidence | | Existing artifacts on an older platform | keep linking | may not link at all | The first row is the one library authors care about. On a discarding platform, a routine that needs to know its argument has to be handed evidence by its caller, and every library that needs it publishes that requirement in its signatures, forever. Keeping the argument removes that tax from every such library - and that is exactly the benefit a platform with no installed base can buy outright, while one with an installed base would be spending its users' rebuild budget to get it. ## Checking is not part of the trade A common error is to present this as a choice between checking early and checking late. It is not. Keeping the argument does not remove compile-time checking and does not make it optional; a platform that verified nothing until the program ran would report mismatches as production failures instead of build failures, which no designer wants. Keeping the argument *adds* what running code may observe, on top of the static checking that both kinds of platform do. ## How to answer it well Price the three buckets - metadata, runtime complexity, per-operation work - and then say who the bill is charged to. A platform starting fresh charges it to itself, once. A platform with a decade of compiled artifacts in the field charges it to every user who would have to rebuild, which is why platforms in that position have generally chosen to discard the argument and let library authors pass evidence instead.
- Does keeping type arguments at run time remove the need for compile-time checking?No. Static checking is what catches mistakes before anything runs, and both kinds of platform do it. Keeping the argument only adds what running code may observe. A platform that waited until run time to check would turn build errors into production failures, which is strictly worse than either design.
- Where does the cost land first in a program heavy on parameterized values - space or time?Usually space and indirection before raw speed: every distinct instantiation needs its descriptor, and values or frames reference it. The time cost shows up where the argument must be forwarded or compared on a hot path - tight loops over parameterized containers, and deeply nested generic calls that each pass the descriptor onward.
- Why is this decision so much cheaper for a platform being designed from scratch?Because the expensive half is the run-time system, and a new platform is building one anyway. There are no deployed artifacts whose shape must stay recognisable and no users to send a rebuild bill to, so the choice is made once by the designers rather than paid for by an ecosystem.
saying these in an interview costs you the question
- Assumes keeping arguments is free because the compiler already knew them
- Says a platform that keeps arguments can drop compile-time checking
- Thinks the only cost is a slightly larger artifact on disk
- Claims arguments can only survive by compiling one body per instantiation
- Claims discarding arguments is required for a single shared compiled body