Implementing a Custom _.partial() Function in JavaScript
The _.partial
method from Lodash allows you to create a function that pre-fills some of its arguments, leaving the rest to be provided later. This technique is known as partial application.
Let's implement a custom version of _.partial
in JavaScript.
What is Partial Application?
Partial application refers to the process of fixing a number of arguments to a function, producing a new function with a smaller arity (number of arguments). It’s useful for creating more specific functions from general-purpose ones.
Real Interview Insights
Interviewers might ask you to:
- Implement a function that mimics the behavior of Lodash’s
_.partial
. - Handle edge cases such as functions with varying numbers of arguments and placeholders.
Implementing customPartial
Function
Here’s how you can implement a custom _.partial
function:
function customPartial(func, ...boundArgs) {
return function(...remainingArgs) {
let args = boundArgs.slice();
let i = 0;
// Replace placeholders with actual arguments
for (let j = 0; j < args.length; j++) {
if (args[j] === customPartial.placeholder) {
args[j] = remainingArgs[i++];
}
}
// Concatenate remaining arguments
args = args.concat(remainingArgs.slice(i));
return func.apply(this, args);
};
}
// Define a placeholder
customPartial.placeholder = '_';
Explanation:
- Argument Binding: The
boundArgs
are the arguments provided when creating the partial function. These are stored and partially fill the function's parameters. - Handling Placeholders: If a placeholder is found in
boundArgs
, it is replaced with the corresponding argument fromremainingArgs
. - Applying the Function: The resulting arguments array is then passed to the original function using
func.apply
.
Practical Examples
Let's see the customPartial
function in action:
function greet(greeting, name, exclamation) {
return `${greeting}, ${name}${exclamation}`;
}
const greetHello = customPartial(greet, 'Hello', customPartial.placeholder, '!');
console.log(greetHello('John')); // Output: 'Hello, John!'
const greetHi = customPartial(greet, 'Hi', 'Sam');
console.log(greetHi('!!')); // Output: 'Hi, Sam!!'
Handling Edge Cases
- No Bound Arguments: If no arguments are bound, the function behaves like the original function.
- Multiple Placeholders: Handle cases where multiple placeholders are used, and the correct mapping of arguments is maintained.
Enhanced Implementation with Multiple Placeholders
function customPartial(func, ...boundArgs) {
return function(...remainingArgs) {
let args = boundArgs.slice();
let i = 0;
// Replace placeholders with actual arguments
for (let j = 0; j < args.length; j++) {
if (args[j] === customPartial.placeholder) {
args[j] = remainingArgs[i++];
}
}
// Concatenate remaining arguments
args = args.concat(remainingArgs.slice(i));
return func.apply(this, args);
};
}
customPartial.placeholder = '_';
Use Cases for Partial Application
- Function Customization: Create specialized versions of general-purpose functions.
- Currying: Partial application can be a step towards currying, where a function with multiple arguments is transformed into a series of functions with single arguments.
- Code Reusability: Reuse logic by binding specific parameters and creating new functions.