When registering an editor shortcut, when is a named function declaration better than an inline literal?
answer
- same value, different spelling
- does anything else need it
- one name, two binding sites
- a name is callable by a test
- a long body hides inside the table
basics
~20 sPrefer a named declaration when something else needs the same behaviour - a second binding, a direct test, or a later removal. An inline literal is right when the body exists only to fit the registration site's shape.
solid answer
~40 sBoth spellings produce a function value of the same kind, and the table cannot tell them apart, so the choice is about **reference and readability, not capability**. A name gives you one value that several sites can refer to: the same delete-line behaviour bound to a shortcut and to a menu item, called directly by a test, and handed back later to unbind. It also gives the body a place to live outside a table that is meant to be scanned as an index. An inline literal wins when the body is a one-line adapter that exists only to match the registration shape - naming it adds a hop for the reader and nothing else. A table of twenty inline bodies is no longer readable as a key map.
code
pseudocode · 14 lines// inline literal: the body lives inside the table
table["ctrl+d"] = function()
line = currentLine()
deleteRange(line.start, line.end)
end
// named declaration: one value, bound in two places
function deleteLine()
line = currentLine()
deleteRange(line.start, line.end)
end
table["ctrl+d"] = deleteLine
menu["Delete line"] = deleteLinego deeper
Know that both spellings produce a function value and that the table cannot tell them apart; reach for a name as soon as something else needs the same behaviour.
Give the criteria rather than a preference: reuse across binding sites, independent testing, later removal, and how the registration table reads when scanned.
Point at the maintenance consequence - a table of twenty inline bodies stops being scannable, while a table of twenty names is an index whose entries live where they are tested.
Set the convention for the codebase, such as inline only one-line adapters, and say how review enforces it and what it costs a contributor who disagrees.
## Two spellings, one kind of value A named declaration and an inline literal both evaluate to a function value. Once the value is in the entry, nothing downstream can distinguish them: the dispatcher looks the key up and applies what it finds either way. So the decision is never about what the entry *can do*. It is about who else can refer to that value, and about what the registration site reads like. ## What a name gives you - **A second binding.** The same behaviour can sit under a keyboard shortcut and under a menu item, with one body and one place to fix a bug. - **A direct test.** A test can call the behaviour without going through the table or simulating an event. - **A handle for later.** Something that must be unregistered, replaced or compared later needs a value you can refer to twice. - **A readable registration site.** A table of names reads as an index: key on the left, intent on the right, one line each. - **Better diagnostics, usually.** Many environments show a declared name where an anonymous value shows nothing useful; languages differ in how much they recover, so treat this as a tendency rather than a guarantee. ## What an inline literal gives you - **Locality.** A one-line body is read where it is used, with no jump to a declaration elsewhere. - **No invented vocabulary.** An adapter that only reorders two arguments has no honest name; inventing one adds a term the codebase must now carry. - **No accidental reuse.** Something written for exactly one binding cannot be grabbed by a second caller who then constrains it. ## Choosing | situation | form | why | |---|---|---| | Behaviour bound at two sites | named | one body, one fix | | Behaviour worth testing on its own | named | tests call it directly | | Binding may be removed later | named | one value to hand back | | One-line adapter to fit the table | inline | a name adds a hop, not meaning | | Body runs to several steps | named | a table is not a place to read logic | The rule that falls out of the table is short: **name it when something else needs it; inline it when nothing does.** Reuse, testing and removal are the three concrete forms of *something else needs it*, and they are the ones to say out loud in an interview, because they replace a style opinion with a criterion. ## What goes wrong with the extremes Two failure modes sit at either end, and both are common in real codebases: 1. **Everything inline.** The registration table grows to a screen of nested bodies. It is no longer scannable as a key map, the bodies cannot be tested except through registration, and any behaviour needed twice gets copied - after which the two copies drift. 2. **Everything named.** Every trivial adapter gets a declaration, so reading one binding costs a jump, and the module's namespace fills with names like `handleCtrlD` that mean nothing except *this fills that slot*. The vocabulary of the file stops describing the domain. Neither extreme is a matter of taste once the codebase is large enough: the first destroys the table's readability, the second destroys the module's vocabulary. ## A convention that survives a large table A workable team rule, stated as three steps: 1. Inline only when the whole body fits on one line and calls something that already exists. 2. Name anything with a branch, a loop, or more than one statement. 3. Name anything bound in more than one place, tested on its own, or removed later. That rule is enforceable in review without argument, because each clause is a fact about the code rather than a preference. It also keeps the registration table doing the job it was built for: being the one place a reader can see, at a glance, which key does what. ## The point an interviewer is checking The answer to avoid is a blanket preference in either direction. What a strong candidate shows is that the two forms produce the same kind of value, that the choice therefore cannot change what the entry can do, and that the real criteria are reuse, testability, removal and how the registration site reads. That is a small amount of knowledge applied precisely, which is exactly what the question is for.
- Does the choice change what the table entry is able to do?No. Both forms evaluate to a function value with the same capabilities, and the entry cannot tell them apart. What changes is whether anything else can refer to that same value, and what the registration site reads like.
- When is an inline literal clearly the better choice?When the body exists only to adapt an existing routine to the registration shape: one line, one binding site, nothing to test separately and nothing to remove later. Naming it adds a jump for the reader and a term to the module's vocabulary without adding meaning.
saying these in an interview costs you the question
- Says an inline literal is inherently slower than a named one
- Thinks only a named declaration produces a real function value
- Claims naming is always better, regardless of reuse
- Believes behaviour written inline cannot be tested at all
- Treats the choice as a style rule rather than a reuse question