检查柯里化函数是否仍需要更多参数
Check if a curried function is still expecting further arguments
我想知道是否有可能在 javascript 中找出柯里化函数期望的剩余参数数量,如果可能的话,而无需实际调用该函数。
我想要一个接受函数和 returns 的函数,如果该函数需要 2 个或更多剩余参数。
hasSeveralRemainingArguments: fn => bool
假设我有以下功能:
const double = x => 2*x;
const inc = x => x + 1;
const divideBy = ({dividor}) => x => x/dividor;
const decrementAndDivideBy = ({dividor}) => x => (x - 1)/dividor;
hasSeveralRemainingArguments(double); // false
hasSeveralRemainingArguments(inc); // false
hasSeveralRemainingArguments(divideBy); // true
hasSeveralRemainingArguments(divideBy({dividor: 5})); // false
hasSeveralRemainingArguments(decrementAndDivideBy); // true
hasSeveralRemainingArguments(decrementAndDivideBy({dividor: 5})); // false
用例将是一个函数 foo
,它需要一个选项参数和一个要调用的函数数组。我想通过函数数组“pipe
”并将选项参数仅输入到实际期望参数的函数,如在本例中 divideBy
和 decrementAndDivideBy
,例如:
const pipe = (...fns) => x => fns.reduce((y, fn) => fn(y), x);
const foo = (options = {}) => (fns = []) => pipe(
fns.map(fn => (
hasSeveralRemainingArguments(fn) ?
fn(options) :
fn
)
);
const bar = (...fns) => {
const options = {
dividor: 3
}; // local, not known to the caller of bar. They just know that they can pass in a function which will receive an options-object, they just don't know what is inside this object.
return foo(options)(fns);
});
const baz = bar(
double,
inc,
divideBy,
decrementAndDivideBy
);
baz(4); // ((4*2 + 1)/3 - 1)/3 = 0.67
baz(10); // ((10*2 + 1)/3 - 1)/3 = 2
函数 bar
的调用者不知道 options
参数。否则我可以在将函数传递给 bar
之前输入 options
参数,但不幸的是这是不可能的。
您还应注意 double
、inc
、divideBy
和 decrementAndDivideBy
仅接受数字作为参数 x
但这可能并非总是如此。如果可能的话,我不想调用函数并测试返回值是否是函数,但目前我看不到任何其他方式。
我也可以传递带有函数和布尔值的对象 "isExpectingOptions" 但这对于调用 bar
.
的人来说不是很 nice/elegant
你有别的想法吗?
您是否考虑过使用函数的 length
属性?
The length property indicates the number of parameters expected by the function.
const a = curry((x, y, z) => 42);
a.length // 3
a(1).length // 2
a(1)(2).length // 1
正如已经指出的,
你可以检查功能的重要性,
然而,如果手动实现柯里化,这就不起作用了。
const nSum = R.curry((a, b, c) => {
console.log('nSum.length', nSum.length);
return a + b + c;
});
const uSum = (a) => (b) => (c) => {
console.log('uSum.length', uSum.length);
return a + b + c;
};
nSum(1, 2, 3);
uSum(1)(2)(3);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js" integrity="sha256-buL0byPvI/XRDFscnSc/e0q+sLA65O9y+rbF+0O/4FE=" crossorigin="anonymous"></script>
您可以构建一个 getArity
函数,
但这需要应用函数来提取其参数的数量...
const getArity = (fn, arg) => {
const res = fn(arg);
return 1 + (
typeof res === 'function' ? getArity(res, arg) : 0
);
};
const uSum = (a) => (b) => (c) => a + b + c;
console.log(
getArity(uSum, 0),
);
const sum2 = uSum(0);
console.log(
getArity(sum2, 0),
);
同样,这个函数并没有真正告诉你函数的元数...
但是如果我们假设它是一元的,可以柯里化多少次。
我想知道是否有可能在 javascript 中找出柯里化函数期望的剩余参数数量,如果可能的话,而无需实际调用该函数。 我想要一个接受函数和 returns 的函数,如果该函数需要 2 个或更多剩余参数。
hasSeveralRemainingArguments: fn => bool
假设我有以下功能:
const double = x => 2*x;
const inc = x => x + 1;
const divideBy = ({dividor}) => x => x/dividor;
const decrementAndDivideBy = ({dividor}) => x => (x - 1)/dividor;
hasSeveralRemainingArguments(double); // false
hasSeveralRemainingArguments(inc); // false
hasSeveralRemainingArguments(divideBy); // true
hasSeveralRemainingArguments(divideBy({dividor: 5})); // false
hasSeveralRemainingArguments(decrementAndDivideBy); // true
hasSeveralRemainingArguments(decrementAndDivideBy({dividor: 5})); // false
用例将是一个函数 foo
,它需要一个选项参数和一个要调用的函数数组。我想通过函数数组“pipe
”并将选项参数仅输入到实际期望参数的函数,如在本例中 divideBy
和 decrementAndDivideBy
,例如:
const pipe = (...fns) => x => fns.reduce((y, fn) => fn(y), x);
const foo = (options = {}) => (fns = []) => pipe(
fns.map(fn => (
hasSeveralRemainingArguments(fn) ?
fn(options) :
fn
)
);
const bar = (...fns) => {
const options = {
dividor: 3
}; // local, not known to the caller of bar. They just know that they can pass in a function which will receive an options-object, they just don't know what is inside this object.
return foo(options)(fns);
});
const baz = bar(
double,
inc,
divideBy,
decrementAndDivideBy
);
baz(4); // ((4*2 + 1)/3 - 1)/3 = 0.67
baz(10); // ((10*2 + 1)/3 - 1)/3 = 2
函数 bar
的调用者不知道 options
参数。否则我可以在将函数传递给 bar
之前输入 options
参数,但不幸的是这是不可能的。
您还应注意 double
、inc
、divideBy
和 decrementAndDivideBy
仅接受数字作为参数 x
但这可能并非总是如此。如果可能的话,我不想调用函数并测试返回值是否是函数,但目前我看不到任何其他方式。
我也可以传递带有函数和布尔值的对象 "isExpectingOptions" 但这对于调用 bar
.
你有别的想法吗?
您是否考虑过使用函数的 length
属性?
The length property indicates the number of parameters expected by the function.
const a = curry((x, y, z) => 42);
a.length // 3
a(1).length // 2
a(1)(2).length // 1
正如已经指出的, 你可以检查功能的重要性, 然而,如果手动实现柯里化,这就不起作用了。
const nSum = R.curry((a, b, c) => {
console.log('nSum.length', nSum.length);
return a + b + c;
});
const uSum = (a) => (b) => (c) => {
console.log('uSum.length', uSum.length);
return a + b + c;
};
nSum(1, 2, 3);
uSum(1)(2)(3);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js" integrity="sha256-buL0byPvI/XRDFscnSc/e0q+sLA65O9y+rbF+0O/4FE=" crossorigin="anonymous"></script>
您可以构建一个 getArity
函数,
但这需要应用函数来提取其参数的数量...
const getArity = (fn, arg) => {
const res = fn(arg);
return 1 + (
typeof res === 'function' ? getArity(res, arg) : 0
);
};
const uSum = (a) => (b) => (c) => a + b + c;
console.log(
getArity(uSum, 0),
);
const sum2 = uSum(0);
console.log(
getArity(sum2, 0),
);
同样,这个函数并没有真正告诉你函数的元数... 但是如果我们假设它是一元的,可以柯里化多少次。