You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否编写符合DRY原则的函数:不重复调用且无额外变量

嘿,这个问题抓得很准——既要按顺序拿到第一个成功的函数结果,又得死死遵守DRY原则:不能多搞没用的临时变量,也绝对不能重复调用函数对吧?先给你拍板:用Maybe(可选值/空值处理)的思路完全可行,而且不管是函数式编程还是面向对象,甚至普通的命令式语言,都有对应的实现方式,下面给你举几个实用的例子:

1. 命令式语言(PHP/JavaScript):用语言原生的空值短路语法

这应该是最贴合你给出的PHP场景的方案,现代语言几乎都自带了这类语法糖,本质就是Maybe模式的简化实现:

PHP示例

function A() {
    // ?? 是PHP的null合并运算符,左边表达式仅执行一次
    return B() ?? C();
}

这个写法完美满足要求:B()只调用一次,没有额外变量,一旦B()返回非null值就直接返回,否则执行C()并返回它的结果。

JavaScript示例

function A() {
    // ES2020+的null合并运算符,逻辑和PHP完全一致
    return B() ?? C();
}

2. 函数式语言(Haskell):用Maybe类型和Alternative组合子

在函数式编程里,Maybe类型就是专门用来处理“可能有值、可能没值”的场景,搭配<|>操作符(Alternative类型类的“尝试”操作),可以非常优雅地实现需求:

-- 假设B和C的返回类型都是Maybe String
a :: Maybe String
a = b <|> c

这里<|>会先计算b(调用B函数),如果结果是Just x(有值)就直接返回;如果是Nothing(空值),再计算c(调用C函数)并返回结果。完全没有重复调用,也不需要临时变量。

3. 面向对象风格:封装可选值的链式调用

如果用OOP的方式,可以自己封装一个Maybe类,通过链式方法来实现“尝试下一个”的逻辑:

PHP OOP示例

class Maybe {
    private $value;

    private function __construct($value) {
        $this->value = $value !== null ? $value : null;
    }

    public static function of($value) {
        return new self($value);
    }

    public function orElse(callable $fn) {
        return $this->value !== null ? $this : self::of($fn());
    }

    public function get() {
        return $this->value;
    }
}

function A() {
    return Maybe::of(B())->orElse('C')->get();
}

这里Maybe::of(B())把B的结果包装成可选值,orElse('C')意思是“如果当前没值,就调用C函数并包装”,最后get()取出值。同样,B和C都只调用一次,没有额外的临时变量。

为什么这些方案符合DRY?

对比你的坏示例就很清楚了:

坏示例1(额外变量):

A() { $B = B(); if($B !== null) { return B(); } return C(); }

这里多了一个不必要的$B变量,而且还重复写了return B(),属于冗余代码。

坏示例2(重复调用):

A() { if(B() !== null) { return B(); } return C(); }

这里B()被调用了两次——如果B是带有副作用的函数(比如写入数据库、修改全局状态),会直接导致逻辑错误,同时重复调用本身也违反了DRY。

而上面的方案,每个函数只调用一次,没有冗余变量,代码逻辑清晰且没有重复。

有没有不可行的情况?

其实只要你用的语言支持短路求值(也就是左边表达式为真/有值时,右边表达式不执行),或者能实现Maybe类型的封装,这个思路就完全可行。唯一可能的例外是一些非常古老的、不支持这类特性的语言,但这类语言现在基本已经被淘汰了。

内容的提问来源于stack exchange,提问作者Paulius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:22:05