检查咖喱函数是否还在期待其他参数。

问题描述 投票:0回答:1

我想知道,如果可能的话,是否可以在不实际调用函数的情况下,在javascript中找出一个咖喱函数所期望的剩余参数的数量。

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

usecase将是一个函数 foo 它需要一个选项参数和一个要调用的函数数组。我想"pipe"通过函数数组,只将选项参数输入到真正期望参数的函数中,比如在本例中的 divideBydecrementAndDivideBy例如:

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

例如: options 参数不为函数的调用者所知。bar. 否则我可以输入 options 参数,然后再将函数传入 bar 但遗憾的是这是不可能的。

您还应该注意到 double, inc, divideBydecrementAndDivideBy 只接受数字作为参数 x 但情况可能并不总是如此。如果可能的话,我不想调用函数并测试返回的值是否是函数,但目前我没有看到任何其他方法。

我也可以通过一个函数和一个布尔值 "isExpectingOptions "来传递对象,但这对调用的人来说不是很好。bar.

你有其他想法吗?

javascript functional-programming currying curry
1个回答
1
投票

你是否考虑过使用 length 函数的长度属性?

长度属性表示函数所期望的参数数量。

const a = curry((x, y, z) => 42);

a.length       // 3
a(1).length    // 2
a(1)(2).length // 1

0
投票

正如已经指出的,你可以检查函数的arity,但是如果是手动实现的,这并不真正有效。

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),
);

这个函数,也没有真正告诉你函数的arity......但如果我们假设它是单数的话,可以策动多少时间。

© www.soinside.com 2019 - 2024. All rights reserved.