猿问

在不重复函数调用和创建额外变量的情况下找到第一个匹配项。有可能吗?

我想从内部按顺序调用函数 B 和 C 的函数 A 中获得第一个成功的结果。


这里的关键点是 - DRY。这意味着我不想引入新变量(例如保持前一个函数调用的结果状态 - 见坏示例#1),我不想重复我的动作(例如两次调用同一个函数 - 见坏示例#2)。


示例代码是用 PHP 编写的,但我不沉迷于 PHP,任何语言都可以接受。OOP,功能性,在这里无关紧要。


到目前为止我发现的可能导致解决方案的概念是使用 Maybe ( https://marcosh.github.io/post/2017/06/16/maybe-in-php.html ),有些人还建议使用 nil ( https://clojure.org/reference/data_structures#nil ) 作为返回类型。但是,我还没有足够的工作示例。我想知道这个解决方案是否可行,我什至开始阅读名为“注释图灵”的书,希望能找到一些指向问题或限制的链接......


坏例子#1(额外变量):


A() {

  $B = B();

  if($B !== null) {

    return B();

  }

  return C();

}

坏例子#2(额外调用):


A() {

  if(B() !== null) {

    return B();

  }

  return C();

}

这里的关键点 - DRY: - 我不希望引入任何额外的变量(坏例子#1)。- 我不希望任何函数运行两次(坏例子#2)。


是否可以在不重复调用和/或将状态保存到额外变量的情况下编写此类代码?


如果是的话 - 我想看看。如果没有,那么我想有一个有效的证明,这是根本不可能写的。


莫回无
浏览 130回答 2
2回答

肥皂起泡泡

这是使用空合并运算符的PHP 7 或更高版本:<?phpfunction a(){&nbsp; &nbsp; return (b() ?? c());}function b(){&nbsp; &nbsp; return null;}function c(){&nbsp; &nbsp; return 'result from c';}var_dump(a());

慕运维8079593

我将展示 JavaScript 中的示例,因为我更熟悉它。这些将是我们的B和C功能:function B() {&nbsp; &nbsp; return Math.random() > 0.5 ? 'B' : null;}function C() {&nbsp; &nbsp; return 'C';}1. 依靠逻辑短路评估 orfunction A() {&nbsp; &nbsp; return B() || C();}请注意,这与您想要的有点不同,因为B()只有当它是非假值时才会返回结果。2. 使用效用函数function firstNonNullResult(functions) {&nbsp; &nbsp; for (const f of functions) {&nbsp; &nbsp; &nbsp; &nbsp; const result = f();&nbsp; &nbsp; &nbsp; &nbsp; if (result !== null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return result;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}function A() {&nbsp; &nbsp; return firstNonNullResult([B, C]);}3. 使用惰性求值某些语言,例如 Haskell,在需要结果之前不会计算表达式,这允许您编写类似find isJust [B, C], whereC仅在不B返回任何内容的情况下进行计算的内容。在 JavaScript 或 PHP 中,您可以使用生成器实现类似的效果。function* map(items, fn) {&nbsp; &nbsp; for (const item of items) {&nbsp; &nbsp; &nbsp; &nbsp; yield fn(item);&nbsp; &nbsp; }}function find(items, predicate) {&nbsp; &nbsp; for (const item of items) {&nbsp; &nbsp; &nbsp; &nbsp; if (predicate(item)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return item;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}function call(fn) {&nbsp; &nbsp; return fn();}function A() {&nbsp; &nbsp; return find(map([B, C], call), x => x !== null)&nbsp; &nbsp;&nbsp;}
随时随地看视频慕课网APP
我要回答