具有多个参数和条件的Ramda

时间:2019-01-23 10:06:16

标签: functional-programming ramda.js

我是函数编程的新手,任何可以帮助我将函数转换为最佳功能的人

const isNotNil = R.complement(R.isNil);
const isFunction = R.is(Function)

const a = (value, value2, fn) => {
   if (isNotNil(value)) {
     return isFunction(fn) ? fn(value) : value
   }
   return value2;
};

a(5,2, R.add(8))

4 个答案:

答案 0 :(得分:1)

在FP中,您应尝试尽可能地分解关注点,并避免使用可选参数,而应使用较小的部分来驱动流程。

此外,Ramda很有用,但缺少一些数据类型,例如Maybe,在这种情况下可能真的有用。看看SanctuaryJS

以下代码使用纯函数方法完全可以实现您想要的

const { toMaybe, maybe, pipe } = sanctuary

const a = f => value => value2 => pipe ([
    toMaybe, // converts to Just (value) or Nothing, when nil
    maybe (value2) (f) // if Nothing, value2, otherwise, value is passed to f
]) (value)

// Output: 3
const output1 = a (x => x + 1) (2) (4)
console.log ('output1: ', output1)

// Output: 4
const output2 = a (x => x + 1) (null) (4)
console.log ('output2: ', output2)
<script src="https://bundle.run/sanctuary@0.15.0"></script>

请注意,我没有检查fFunction。 JavaScript是一种动态类型的语言:只需假设它将是Function,否则它就会快速失败。

利用部分应用程序的重构方法:

const { toMaybe, maybe, pipe } = sanctuary

// Re-arranged parameters: now value is the latest one.
const a = f => value2 => pipe ([
    toMaybe, // converts to Just (value) or Nothing, when nil
    maybe (value2) (f) // if Nothing, value2, otherwise, value is passed to f
])

// Output: 3
const output1 = a (x => x + 1) (4) (2)
console.log ('output1: ', output1)

// Output: 4
const output2 = a (x => x + 1) (4) (null)
console.log ('output2: ', output2)
<script src="https://bundle.run/sanctuary@0.15.0"></script>

答案 1 :(得分:1)

在Ramda中,您倾向于将要操作的数据作为函数的最后一个参数传递。所有其他参数都可以看作是应用于数据的流程的配置。

知道这一点后,您的函数签名应该看起来像:a(defaultValue, func, value)

这使您可以使用预定义的行为来构建咖喱函数:

const incOr42 = a(42, inc);
incOr42(1);    // 2
incOr42(null); // 42

现在让我们看一下将问题分解成小块:

首先,让我们验证func,它本身可以是一个函数:

如果给checkFn的东西不是函数,它将返回一个始终返回其参数的函数。否则,它将返回原始功能

const checkFn = unless(is(Function), always(identity));
checkFn(add(8))(5); // 13
checkFn('foo')(5);  // 5

其次,让我们构建一个接受两个参数的函数:defaultValuefunc。 它将返回一个接受value的函数,如果defaultValue为nil,则返回value,否则返回func

const a = useWith(ifElse(isNil), [always, checkFn]);
const incOr42 = a(42, inc);
incOr42(1);    // 2
incOr42(null); // 42

将所有内容放在一起:

const {unless, is, always, identity, ifElse, isNil, useWith, inc} = R;

const checkFn = unless(is(Function), always(identity));
const a = useWith(ifElse(isNil), [always, checkFn]);

const incOr42 = a(42, inc);

console.log(incOr42(1));
console.log(incOr42(null));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>

答案 2 :(得分:1)

我真的没有太多理由超越显而易见的地方。

此版本似乎完全可以满足您的要求,并且可读性强:

const {is, isNil} = R

const a = (val, val2, fn) => isNil(val) ? val2 : is(Function, fn) ? fn(val) : val

console.log(a(5, 2, R.add(8)))       //=> 13
console.log(a(5, 2, 'NonAFunction')) //=> 5
console.log(a(null, 2, R.add(8)))    //=> 2
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

答案 3 :(得分:1)

您基本上是在发明 Option 类型;有时称为也许。使用像daggy这样的简单标记联合库,我们可以实现 Option -

const daggy = require('daggy')

const Option = daggy.taggedSum('Option', {
  Some: ['x'],
  None: [],
})

const { Some, None } = Option

Option.prototype.map = function(f) {
  return this.cata({
    Some: x => Some(f(x)),
    None: _ => this
  })
}

const add = x => y => x + y

console.log
  ( Some(1).map(add(10)) // Some(11)
  , None.map(add(10)) // None
  )

我们可以添加一个withDefault方法,该方法允许我们返回到正常值-

Option.prototype.withDefault = function (x) {
  return this.cata({
    Some: x => x,
    None: _ => x
  })
}

console.log
  ( Some(1).map(add(10)).withDefault(0) // 11
  , None.map(add(10)).withDefault(0) // 0
  )

最后,一个将普通值转换为我们新的Option类型的构造函数-

Option.fromNullable = function (x) {
  if (x == null)
    return None
  else
    return Some(x)
}

console.log
  ( Option.fromNullable(1).map(add(10)).withDefault(0) // 11
  , Option.fromNullable(null).map(add(10)).withDefault(0) // 0
  )

如果您仍然需要将此表达式表示为函数,例如问题中的a-

const a = R.curry((f, x, y) =>
  Option.fromNullable(x).map(f).withDefault(y))

console.log
  ( a (R.add(8), 5, 2) // 13
  , a (R.add(8), null, 2) // 2
  )

Ramda不包含内置的 Option Maybe ,但是如果您正在寻找现有的实现,npm上有一些流行的模块,例如{{3 }}。