_.partial(fn, ...presetArgs) pre-fills a function's leftmost arguments and returns a new function waiting for the rest. It's the simpler cousin of curry — one call, fixed positions, no arity tracking — but the placeholder extension makes it as powerful.
What is partial()?
partial(fn, ...presetArgs) locks in some arguments now and returns a function that supplies the remaining ones later:
With a placeholder (_), you can fix arguments at any position — not just leftmost:
Partial vs curry:
partialis a one-shot application — call it once with preset args, get back a plain functioncurryaccumulates args across multiple calls and tracks remaining arity- Use
partialwhen you know which specific arguments to fix now; usecurryfor step-by-step argument supply
The Problem
"Implement partial(fn, ...presetArgs) that returns a new function. When called, it merges its arguments with the preset arguments from left to right and calls fn."
The interviewer extends:
"Add placeholder support — partial.placeholder lets you skip preset positions, filling them from the later call's arguments."
Thought Process
Without placeholders, this is just argument prepending: (...laterArgs) => fn(...presetArgs, ...laterArgs).
With placeholders, it's the same merge operation as placeholder curry — scan presetArgs left-to-right, replacing _ entries with later args in order. Any unconsumed later args are appended.
The key difference from curry: partial doesn't count arity. It calls fn immediately when you invoke the returned function — there's no "waiting until we have enough args." You get one deferred call, not a chain.
Step 1 — Base Implementation
Loading editor...
Step 2 — With Placeholder Support
Loading editor...
Step 3 — Edge Cases
Loading editor...
Full Solution
Loading editor...
What Interviewers Are Testing
- Argument prepending — the basic case is just spread:
fn(...presetArgs, ...laterArgs) - Placeholder merge — same
_-as-Symbol + left-to-right fill pattern as placeholder curry, but applied once apply(this, ...)for context — usingfn.apply(this, merged)ensures the partially-applied function works as a method- Partial vs curry distinction — partial is one-shot (call the result once to invoke); curry is multi-step (accumulates until arity satisfied)
partial.placeholderas a property — exposing_so callers can import a single reference
Complexity
| Time | Space | |
|---|---|---|
partial(fn, ...presetArgs) | O(1) | O(P) — stores P preset args |
| Calling the returned function | O(P + L) — merge step | O(P + L) |
Interview Tips
- State the one-sentence difference from curry — "Partial fills the leftmost args now and returns a plain function. Curry wraps the function and chains calls until all args are accumulated."
- Sketch the merge on a whiteboard —
presetArgs = [_, "Alice", _],laterArgs = ["Hello", "!"]→merged = ["Hello", "Alice", "!"]. The visual makes the algorithm obvious. - Use
fn.apply(this, merged)notfn(...merged)— supports partial application on methods wherethismatters. - Compare to
Function.prototype.bind— "The built-inbinddoes the same thing:fn.bind(null, ...presetArgs).partialadds placeholder support on top."