您将如何编写一个从列表中删除元素的“纯”函数?

Chr*_*ris 3 java functional-programming pure-function

在 Java(或任何类似的语言)中,如何编写从列表中删除元素的纯函数(或方法)。

如果该元素在列表中,我们只需返回一个新的(理想情况下不可变的)列表,其中包含输入列表的所有元素,减去我们删除的元素。

但是如果在列表中找不到该元素,您将如何处理?

假设该方法接收 2 个参数,即listelement要删除的参数:

public SOMETHING remove(final List<String> list, final String element){
    // Copy the input list and remove the first occurrence of 'element', if I find it.
    // 
    // if I don't find it ... do something clever here ...
}
Run Code Online (Sandbox Code Playgroud)

如果我调用这个方法,并且element不包含在里面list

  • 抛出异常可能会使方法“不纯”(?)
  • 修改输入列表并返回布尔值(类似于List#remove())可能会使方法“不纯”(修改输入将是副作用)
  • 如果我调用此方法,将输入作为输出返回对我来说似乎不直观。
  • 返回Optional.of(listCopy)(编辑:发布后添加到我的问题中)
  • 还有其他想法吗?

编辑

我应该提到,我只想删除第一次出现的element,因此如果输入list多次出现element,我不想通过对我的remove() 方法的一次调用来删除它们(例如使用stream().filter())来删除它们。我刚刚编辑了代码示例中的注释来反映这一点。然而,这与我的问题并不完全相关,因为我的主要问题围绕如何使该方法直观易用并保持“纯粹”。

编辑2

我在上述建议的基础上添加了一个额外的想法。返回Optional.of(listCopy)似乎是迄今为止所提出的解决方案中最优雅的解决方案。它强制调用者检查请求的操作是否成功,并且(如果成功),它返回一个新列表,从而不会修改原始输入列表。如果操作不成功(element内部未找到list),该方法将返回Optional.empty()。在我看来,这也将满足下面提到的引用完整性

Nir*_*evy 5

Going through the points you mentioned:

  1. Throwing an exception would presumably make method "impure" (?)
    • This is an implementation decision, if you want to return the same list or throw an exception. as for 'pure function' - as long as you're consistent and the same input yields the same result (or exception), you're good
  2. Modifying the input list and returning a boolean (similar to List#remove()) would presumable make the method "impure" (modifying the input would be a side-effect)
    • this will make it non pure functional, as you'll have a side effect
  3. Returning the input as output would seem unintuitive to me if I was calling this method.
    • don't see any problem with that actually. again, your call if it's a valid scenario or not. in terms of 'pure function', you're ok here

as for implementation, I think stream is the simplest, and returns new list so you're ok in terms of purity

return list.stream()
 .filter(e -> !e.equals(element))
 .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)