【问题标题】:PHP: Is there a better way to apply a function to a variable and assign it at the same time?PHP:有没有更好的方法将函数应用于变量并同时分配它?
【发布时间】:2018-04-21 00:03:35
【问题描述】:

这个问题可能看起来有点奇怪——也许答案很简单——但它困扰着我。如果我将一个函数应用于一个变量为什么我必须写两次它的名字

有没有同时apply和assign之类的东西?

例子:

function abc($cat_id) {
    $cat_id = intval($cat_id);
    return $cat_id * $cat_id;
}

我想要:

function abc($cat_id) {
    intval($cat_id); // and apply the new value, but without writing an extra function
    return $cat_id * $cat_id;
}

我正在搜索的伪代码示例是:

intval($cat_id)<=

...一些运算符,例如“将结果分配给输入”。

【问题讨论】:

  • 这样做:- function abc($cat_id) { return $cat_id * (intval($cat_id)); }。顺便说一句,ADyson 说的完全正确。

标签: php variable-assignment


【解决方案1】:

虽然可能有办法通过滥用类型强制来做到这一点,但这根本不是一个好的做法。

以简单的步骤考虑您正在执行的操作:您正在调用一个函数,该函数返回一个结果,然后将该结果分配给一个变量。三个步骤,代码中都有。

您想要隐藏最后一步,这没有任何好处,并且使代码不那么容易理解。

例如:

$a = "something"
some_cool_function($a);

$a 在该函数调用中是否发生了变化?除了查看细节,你无从得知。

总是让突变被第一眼看到会更好。

【讨论】:

  • 当然可以,但是像usort 这样的函数还是会这样做?!如果这是一个简短的函数,我认为这种行为不会影响可读性,尤其是当它通过某个字符可见时。
  • @Blackbam usort 通过引用接收数组变量 - 请参阅文档中的定义。 php.net/manual/en/function.usort.php。 intval 不这样做。所以这取决于函数是如何实现的。在 usort 的情况下,这样做是有理由的 - 对实际数组进行操作以避免产生新数组是明智的(可能会无缘无故地占用大量内存)并且它还希望返回一个真/假成功指标作为输出。不同的用例,IMO。
  • usort 可能会在非常大的数据集上调用,因此生成它的全新副本可能不是正确的举措。但是除非你有这样的特殊原因,否则应该始终显示可变性。这就是为什么大多数 PHP 函数在可能的情况下不会那样做。想一想:你不必无缘无故地写两次,你必须写两次,因为你对它做了两种不同的操作:1.将它作为参数传递,2.赋予它一个新值。您要问的是,“我怎样才能对读者隐藏第二个操作”。你为什么想要那个?
  • 试着把它想象成 1. 它不是你的代码,但是你正在阅读别人的代码,你不想知道事情什么时候发生变化吗?以及 2. 如果它不是一个简单的 intval 而是一个更复杂的函数,其副作用对读者来说不是很清楚(请参阅我在主要答案中的示例),因此您不会“明显知道”它改变值。就像我说的,可变性是应该始终明确暴露的事情之一。
  • 当然我同意你的观点。仍然为什么使用单个字符将结果分配给输入而不是隐藏它是一个坏主意。但作为这次讨论的结果,我想没有这样的事情吗?
【解决方案2】:

我认为,如果值是通过引用传递的,您的建议会起作用。

但是你要做的是得到intval() 函数的输出,因为intval() 函数就是这样工作的。您可能需要/想要创建一个新变量(例如 $x = intval($cat_id); ),这种语法为您提供了这种灵活性,而如果您必须按照您建议的方式进行操作,那么它不会给您选择。这也会使正在发生的事情变得不太清楚 - 除了通过检查或阅读文档之外,不会立即清楚intval() 是否正在更改变量。

在我看来,您的问题“为什么我必须写两次它的名字”并没有多大意义。你只写了两次,因为你选择。您实际上正在做的是将变量 a 作为输入参数发送到函数中,并将变量 b 作为函数的结果输出。它们是不同的变量。 bintval() 处理后新创建的,并作为输出返回给您。

您选择将现有的$cat_id 变量重新分配为现在表示函数结果的事实是您的 选择,与语言无关。正如我上面提到的,您可以将结果分配给另一个变量。

【讨论】:

  • 当然这是我决定重新分配结果的特殊情况。但是拥有&=intval($cat_id)intval($cat_id)<= 之类的东西有什么不好(只是想法)。我想知道是否有类似的东西。
  • 如果你愿意,你可以做return intval($cat_id) * intval($cat_id);。在那种特殊情况下,这意味着您最终会进行两次转换,但这也是间接的,因为您碰巧将数字乘以自身。在这种特定情况下,您现有的代码的执行效率更高,即使编写起来有点冗长。
  • 如果您将两个不同的数字相乘,例如return intval($cat_id) * intval($x); 那将是合理的编写方式。但请注意,乘法是在 intval() 的输出上完成的,而不是在原始变量上完成的。乘法运算完成后,$cat_id$x 仍然是字符串(实际上,从技术上讲,在这种情况下,它们不再存在,因为函数立即返回,但关键是这些变量本身并没有变异为整数 - 相反, 新变量由intval() 创建并返回给乘法运算符)。
【解决方案3】:

你可以这样做

function abc($cat_id) {
    return (int)$cat_id * (int)$cat_id;
}

【讨论】:

  • 谢谢,但这仅适用于这种特殊情况,我正在寻找一种更通用的方法。
  • 写一个函数来做你想做的事情function myintval(&$var){ $var=intval($var); }
  • 不完全是我想要的,但你提出了一个好主意。
【解决方案4】:

好吧,我找到了一个解决方案 - 你可能讨厌它,但它可以满足我的需求,即使是多个功能:

/**
 * Apply 1..n one parameter functions to the given variable.
 *
 * @param array/mixed $callback: An array of Callback functions which accept one parameter.
 * @param $var: The variable to apply them to.
 */
function §($callback,&$var) {
    if(is_array($callback)) {
        foreach($callback as $c) {
            $var = $c($var);
        }
    } else {
        $var = $callback($var);
    }
}

$a = "4";

§('intval',$a);

var_dump($a);

§(['intval','exp','ceil'],$a);

var_dump($a);

结果:

int(4)

浮点数(55)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-05
    • 2020-10-28
    • 2018-09-09
    • 2011-04-04
    • 2017-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多