java - 柯里化一个现有的静态函数

java - curry an existing static function

为了充分利用 Java 中的函数组合,我想柯里化一些我常用的现有静态函数。 Apache Commons StringUtils.

是柯里化的完美候选者

举个具体的例子,假设我想柯里化 StringUtils.remove(String str, String remove) 方法以提供一个名为(比如)removeCommas.

的函数

一种可能的实现方式是:

Function<String, String> removeCommas = s -> StringUtils.remove(s, ",");

但这不是柯里化。我希望能够使用方法引用运算符(例如 StringUtils::remove)以更实用的方式实现这一点,但我无法弄清楚语法是什么样的。

想法?

函数式语言有柯里化,因为许多函数式语言仅限于只有一个参数的函数。这是从lambda演算继承下来的,是数理逻辑学科中形式化的language/system

Currying 克服了这个限制,但是 plain Java 不支持 currying。


几年前我编写了一个名为 jcurry, here is an example 的库。也许你觉得有用。

你可以这样咖喱 remove()

Function<String, Function<String, String>> remove = r -> s -> StringUtils.remove(s, r);
Function<String, String> removeCommas = remove.apply(",");

如果您更喜欢方法引用,您可以制作一个通用的辅助方法来柯里化任何固定数量的方法:

static <T, U, R> Function<T, Function<U, R>> curry(BiFunction<T, U, R> function) {
    return a -> b -> function.apply(a, b);
}
// ...
Function<String, Function<String, String>> remove = curry(StringUtils::remove);

请注意,此助手遵循参数顺序,因此上述函数将在删除字符串之前捕获目标字符串。无法对方法引用中的参数重新排序,因此您必须选择一个顺序并坚持下去。

Plain Java 不提供柯里化语法糖。但是,如果您愿意使用第三方库,则可以使用 Javaslang.

除了元数为 0..8 的函数外,它还包含允许抛出异常的已检查函数(相同元数)。它们提供以下功能:

  • 部分申请
  • 柯里化函数
  • 元组函数
  • 记忆函数(=结果缓存)
  • 具有反向参数的函数
  • 功能提升
  • ...

在我们这里的具体案例中,我们需要在柯里化(或部分应用)remove 方法之前反转参数列表:

// currying
final Function1<String, Function1<String, String>> curried =
        Function2.of(StringUtils::remove).reversed().curried();

// partial application with reversed parameters
final Function1<String, String> removeCommas =
        Function2.of(StringUtils::remove).reversed().apply(",");

Function1 扩展了 Java 的 Function,Function2 扩展了 Java 的 BiFunction 以实现互操作性。

免责声明:我是 Java俚语

的创造者