【问题标题】:Function composition in JavaJava中的函数组合
【发布时间】:2009-11-19 20:57:05
【问题描述】:

我正在尝试实现一个惰性序列(意味着仅在您调用 step 函数时才计算下一项),它应该具有的方法之一是“map”,它接收一个影响所有成员。
最优雅的方法是使用函数组合,并将新函数分配给函数变量,但由于函数不是 Java 中的第一类值,我不知道该怎么做。

我想过有一个只包含一个函数的类,作为一种“函数指针”包装器,但我不明白它如何用于组合。

编辑:问题与作业有关。
此外,它应该能够按照map(map(map(stepFunction()))) 的方式处理多个组合(在这种情况下,“map”是通过方法“map”给出的函数)。

【问题讨论】:

  • 所以当你说你想做 map(map(map(stepFunction()))) 时,这是否意味着你有一个列表列表并且你想在每个列表上调用 stepFunction该层次结构中所有子列表的元素?我仍然不完全清楚您要完成的工作。
  • 没有。基本上就是这样:在任何给定时间我只有三件事:阶跃函数、当前值和基值。如果从未应用 Seq.map(someFunctionToMapWith),则当前值 = 基值 = stepFunction(以前的基值)。但是,一旦将 map 应用于序列,每次我调用 seq.tail() 来更改当前值时,我首先更改基值并使用给定的函数进一步改变它: curr = mapFunc(stepFunc(base value )) (基值也会更新)。如果 map 被多次调用,它应该是 map(map(..map(stepFunc(base value))..))。

标签: java function-composition


【解决方案1】:

欢迎来到 Java 及其痛苦。

interface Function<T> {
    public T eval(T argument);
}

class Lazy<T> {
    private Iterator<T> source;
    private Function<T> filter;
    Lazy(final Iterator<t> source, final Function<T> filter) {
        this.source = source;
        this.filter = filter;
    }
    public T step() {
        return filter.eval(source.next());
    }
}

【讨论】:

  • 我看不出这对我的构图有何帮助。也许我应该提到它应该能够响应map()的多种应用。我要实现的行为是map(map(map(stepFunction())))(例如)。
  • 然后让 Lazy 扩展 Iterator... 这个想法是给你一个正确方向的指针,而不是写你所有的代码!
  • @EpsilonVector 考虑将其改为流畅的界面,因此:stepFunction().map(Functor).map(Functor).take(5) 或其他
【解决方案2】:

Google CollectionsFunction 类型、Functions.compose(Function, Function) 方法、Iterables.transform(Iterable, Function) 方法等等。

如果这是家庭作业,对你没有帮助(我真的希望每个人在他们的问题与家庭作业相关时都能透露)。

【讨论】:

    【解决方案3】:

    在 Java 中,您总是使用类协议来执行此操作。有关规范示例,请参阅 java.lang.Thread 和 run 函数。 Java 中没有“函数指针”或“函数变量”。

    【讨论】:

      【解决方案4】:

      FWIW,Java 中的“函数指针”等价物是具有单个方法的 接口。您使用某个类实现接口,该类提供方法的实现,然后存储对该类对象的引用。

      更改对另一个类对象的引用,实现方法不同,相当于将函数指针更改为指向不同的函数。

      【讨论】:

        【解决方案5】:

        Java 8 添加了 java.util.function 包,这使得可以做原始问题所要求的 (https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html):

        Function<Integer, Integer> multiply = (value) -> value * 3;
        Function<Integer, Integer> add      = (value) -> value + 2;
        
        Function<Integer, Integer> addThenMultiply = multiply.compose(add);
        
        Integer result1 = addThenMultiply.apply(3);
        System.out.println(result1); // 15
        

        它仍然不是超级好,但这是问题中要求的同时使用组合和懒惰......

        【讨论】:

          【解决方案6】:
          public static <T> void apply(final List<T> list, final Function<T> func)
          {
              for(final T val : list)
              {
                  func.perform(val);
              }
          }
          
          interface Function<T>
          {
              void apply(T value);
          }
          
          class DisplayFunction<T>
              implements Function<T>
          {
              public void perform(T value)
              {
                  System.out.println(value);
              }
          }
          

          调用apply(list, new DisplayFunction());

          【讨论】:

          • 并且毫无理由的随机降级仍然明显发生。如果您认为有问题,请解释您为什么这么认为是有礼貌的。
          • 这可能是因为它没有回答问题,即如何组合两个函数,而不仅仅是使用一个映射。此外,函数实际上并不修改它们的输入,它们返回一个单独的转换值。
          • 您可以将其更改为 public static R apply(final List list, final Function func) 以使其返回不同的值(或删除 R 并使用T 为返回值,如果返回值将相同)。一般来说,我不会直接回答作业……但这个答案应该足以让事情开始了。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-10-06
          • 1970-01-01
          • 2013-08-08
          • 1970-01-01
          • 2012-11-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多