Implement partial() — Pre-fill Function Arguments

partial(fn, ...presetArgs) locks in leftmost arguments and returns a new function for the rest. Add placeholder support to fix any position — the built-in bind() without the this binding.

10 min read
JavaScript
Interview
Implementation
Functional

TABLE OF CONTENTS

_.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:

  • partial is a one-shot application — call it once with preset args, get back a plain function
  • curry accumulates args across multiple calls and tracks remaining arity
  • Use partial when you know which specific arguments to fix now; use curry for 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 — using fn.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.placeholder as a property — exposing _ so callers can import a single reference

Complexity

TimeSpace
partial(fn, ...presetArgs)O(1)O(P) — stores P preset args
Calling the returned functionO(P + L) — merge stepO(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 whiteboardpresetArgs = [_, "Alice", _], laterArgs = ["Hello", "!"]merged = ["Hello", "Alice", "!"]. The visual makes the algorithm obvious.
  • Use fn.apply(this, merged) not fn(...merged) — supports partial application on methods where this matters.
  • Compare to Function.prototype.bind — "The built-in bind does the same thing: fn.bind(null, ...presetArgs). partial adds placeholder support on top."

Related Questions


Let's Connect

© 2026 Naveen Karthik // Built with React & MUI