深入理解PHP中的高阶函数:提升代码灵活性和可重用性
许多大型应用和框架中都广泛使用高阶函数。JavaScript、Java、.NET、Python甚至PHP等多种编程语言都支持高阶函数的概念。但什么是高阶函数?为什么我们要使用它?它有哪些优势?如何用它简化代码?本文将重点介绍PHP中的高阶函数,并与其他语言进行比较。
callable
可以用来识别高阶函数。如果一个函数或方法具有callable
参数,则表示它接受函数作为输入。array_map
和array_filter
。这些函数接受回调函数作为参数,并以不同的方式将其应用于数组的元素。calc()
的函数,它接受几个输入函数并对几个参数进行操作。在了解高阶函数之前,必须先了解支持一等函数(也称为一阶函数)的语言特性。这意味着该语言将函数视为一等公民。换句话说,该语言对函数的处理方式与对变量的处理方式相同。您可以将函数存储在变量中,将其作为变量传递给其他函数,像变量一样从函数中返回它们,甚至可以像使用变量一样将它们存储在数组或对象属性中。如今,大多数现代语言默认都具有此特性。您只需要知道函数可以像变量一样传递和使用即可。
本文将主要关注将函数作为参数传递和将函数作为结果返回,并简要介绍非局部变量和闭包的概念。(您可以在前面段落中链接到的维基百科文章的1.1、1.4和1.3节中阅读更多关于这些概念的信息。)
高阶函数有两个主要特征。高阶函数可以实现以下一个或两个特性:接受一个或多个函数作为输入,或返回一个函数作为输出。在PHP中,有一个关键字可以清楚地表明一个函数是高阶函数:关键字callable
。虽然此关键字并非必须存在,但它使识别高阶函数变得容易。如果您看到一个函数或方法具有callable
参数,则表示它接受函数作为输入。另一个简单的标志是,如果您看到一个函数使用其return
语句返回一个函数。return
语句可能只是函数的名称,也可能是一个匿名/内联函数。以下是一些每种类型的示例。
// 我们将传递给高阶函数的简单用户定义函数 function echoHelloWorld() { echo "Hello World!"; } // 接受函数作为输入并调用它的高阶函数 function higherOrderFunction(callable $func) { $func(); } // 调用我们的高阶函数并传入我们的echoHelloWorld()函数。 // 请注意,我们只将名称作为字符串传递,没有括号。 // 这将输出 "Hello World!" higherOrderFunction('echoHelloWorld');
以下是一些返回函数的高阶函数的简单示例:
// 返回PHP中名为trim()的现有函数。注意它是一个简单的字符串,没有括号。 function trimMessage1() { return 'trim'; } // 这是一个使用匿名内联函数的示例 function trimMessage2() { return function($text) { return trim($text); }; } // 返回'trim'函数 $trim1 = trimMessage1(); // 使用我们的字符串进行修剪并调用它 echo $trim1(' hello world '); // 返回内部调用'trim'的匿名函数 $trim2 = trimMessage1(); // 使用我们的字符串进行修剪并再次调用它 echo $trim2(' hello world ');
您可以想象,您可以传入一个函数,并使用它来生成另一个返回的函数。很巧妙的技巧,对吧?但是为什么要这样做呢?这听起来像是会使事情变得更复杂的东西。
您可能需要在代码中创建高阶函数的原因有很多。从代码灵活性、代码重用、代码扩展到模仿您在其他程序中看到的代码解决方案,不一而足。虽然原因很多,但这里我们将介绍其中几个。
高阶函数增加了大量的灵活性。根据前面的示例,您可能已经看到了一些用途。您可以编写一个单一函数,该函数接收整套不同的函数并使用它们,而无需编写代码来单独执行它们。
也许高阶函数本身并不知道它将接收什么类型的函数。谁说函数必须了解它接收的函数的任何信息?一会儿输入函数可能是add()
函数,下一刻它可能是divide()
函数。无论哪种情况,它都能正常工作。
此功能还可以更轻松地以后添加其他输入函数。假设您有add()
和divide()
,但以后需要添加sum()
函数。您可以编写sum()
函数并将其通过高阶函数传递,而无需更改高阶函数。在后面的示例中,我们将演示如何使用此功能来创建我们自己的calc()
函数。
您可能想要在PHP中使用高阶函数的另一个原因是模拟Python中装饰器的行为。您将一个函数“包装”在另一个函数中以修改该函数的行为。例如,您可以编写一个函数来计时其他函数。您可以编写一个高阶函数,该函数接收一个函数,启动计时器,调用该函数,然后结束计时器以查看经过了多少时间。
在PHP中找到高阶函数的示例非常简单。查看PHP文档,找到一个接受callable
输入参数的函数/方法,您就找到了一个。以下是一些常用高阶函数的示例。您甚至可能在不知情的情况下使用过它们。
array_map
和array_filter
// 我们将传递给高阶函数的简单用户定义函数 function echoHelloWorld() { echo "Hello World!"; } // 接受函数作为输入并调用它的高阶函数 function higherOrderFunction(callable $func) { $func(); } // 调用我们的高阶函数并传入我们的echoHelloWorld()函数。 // 请注意,我们只将名称作为字符串传递,没有括号。 // 这将输出 "Hello World!" higherOrderFunction('echoHelloWorld');
让我们看看如何使用另一个函数,这次使用我们单独定义的过滤器函数:
// 返回PHP中名为trim()的现有函数。注意它是一个简单的字符串,没有括号。 function trimMessage1() { return 'trim'; } // 这是一个使用匿名内联函数的示例 function trimMessage2() { return function($text) { return trim($text); }; } // 返回'trim'函数 $trim1 = trimMessage1(); // 使用我们的字符串进行修剪并调用它 echo $trim1(' hello world '); // 返回内部调用'trim'的匿名函数 $trim2 = trimMessage1(); // 使用我们的字符串进行修剪并再次调用它 echo $trim2(' hello world ');
array_filter
和array_map
是您会在许多代码项目中找到的两个非常流行的高阶函数。另一个您可能会使用的函数是call_user_func
,它接收一个函数和一个参数列表,并调用该函数。这本质上是一个自定义的高阶函数。它的全部目的是调用用户定义的其他函数:
$arrayOfNums = [1,2,3,4,5]; // array_map:使用内联匿名函数的示例 $doubledNums = array_map(function($num) { return $num * 2; }, $arrayOfNums); var_dump($doubledNums); // 输出包含 [2, 4, 6, 8, 10] 的数组
我们已经展示了高阶函数在PHP中如何工作的许多示例,并且我们已经创建了一些自定义函数来演示它们的各种用途。但是,让我们用一个名为calc()
的新函数来进一步展示其灵活性。此函数将接收两个参数和一个函数,该函数将对这两个参数进行操作以给我们一个结果:
$arrayOfNums = [1,2,3,4,5]; // 创建函数并将其提供给高阶函数array_filter()的示例 function isEven($num) { return ($num % 2) === 0; } // array_filter是一个高阶函数 $evenNums = array_filter($arrayOfNums, 'isEven'); var_dump($evenNums); // 输出包含 [2, 4] 的数组
请注意,我们的calc()
函数的编写非常通用,可以接收一组其他函数并使用参数$n1
和$n2
调用它们。在这种情况下,我们的计算函数并不关心它接收的函数做了什么。它只是将参数传递给函数并返回结果。
但是等等:我们的老板刚刚要求我们在现有系统中添加一个函数来将两个字符串加在一起。但是连接字符串不是您典型的数学运算。但是,使用我们这里的设置,我们只需要添加字符串连接并将其通过calc()
传递:
function printCustomMessage($message) { echo "$message"; } call_user_func('printCustomMessage', '通过使用call_user_func调用自定义消息!');
虽然此示例非常牵强,但它演示了您如何在大型项目中使用此概念。也许高阶函数决定了如何处理事件。也许,根据触发的事件,您可以通过您传入的处理程序函数将其路由。可能性是无限的。
让我们以Python中的一个简单装饰器为例,并将其与JavaScript进行比较,然后将其与PHP进行比较。这样,如果您了解Python或JS,您可以看到它是等效的。
function add($a, $b) { return $a + $b; } function subtract($a, $b) { return $a - $b; } function multiply($a, $b) { return $a * $b; } // 传递$n1和$n2的高阶函数 function calc($n1, $n2, $math_func) { return $math_func($n1, $n2); } $addedNums = calc(1, 5, 'add'); $subtractedNums = calc(1, 5, 'subtract'); $multipliedNums = calc(1, 5, 'multiply'); // 输出 6 echo "相加的数字:$addedNums\n"; // 输出 -4 echo "相减的数字:$subtractedNums\n"; // 输出 5 echo "相乘的数字:$multipliedNums\n";
现在让我们看看如何在JavaScript高阶函数中实现这一点:
function addTwoStrings($a, $b) { return $a . " " . $b; } // 输出 "Hello World!" $concatenatedStrings = calc('Hello', 'World!', 'addTwoStrings');
最后,让我们将其与PHP进行比较:
def say_message(func): def wrapper(): print('调用函数之前打印') func() print('调用函数之后打印') return wrapper def say_hello_world(): print("Hello World!") # 将我们的hello world函数传递给say_message函数。 # 它返回一个函数,然后我们可以调用它 # 注意:这一行可以用say_hello_world方法上的@say_message(派语法)代替 say_hello_world = say_message(say_hello_world) # 调用创建的函数 say_hello_world() # 输出... # 调用函数之前打印 # Hello World! # 调用函数之后打印
从并排比较中可以看出,PHP版本与JavaScript语法非常相似。但是,如果您了解一些Python和装饰器知识,您可以看到如何将装饰器转换为另外两种编程语言之一。
在使用高阶函数时,您经常会看到内联匿名函数(也称为lambda)的使用。在上面我们看到的示例中,我已经使用了这种格式。除此之外,我还使用了首先定义函数然后将其传递给高阶函数的更明确的版本。这是为了让您习惯看到这两个版本。大多数情况下,您会在大量使用高阶函数的框架中看到内联lambda版本。不要让这种格式吓倒您。它们只是在没有名称的情况下创建一个简单的函数,并将其用于您提供独立函数名称的位置。
在本文中,我们介绍了使函数成为高阶函数的基本定义。任何接受函数或返回函数(或两者兼而有之)的函数都可以被认为是高阶函数。我们还讨论了您可能想要创建这些类型的函数的原因以及它们的优势。
然后,我们展示了PHP中现有高阶函数的一些示例,例如array_map
和array_filter
,然后继续创建我们自己的名为calc()
的高阶函数,该函数接受几个输入函数并对几个参数进行操作。然后,我们进行了并排比较,展示了PHP的解决方案与Python装饰器和JavaScript实现相比如何。我希望您能更多地了解高阶函数以及您可能需要在下一个大型解决方案中考虑它们的原因。它们可以提供许多优势并减少可能冗余的样板代码。
如果您想了解有关PHP中函数式编程的更多信息,可以参考我们的教程。
感谢您的阅读!
PHP中的高阶函数是函数式编程中的一个基本概念。它们是可以对其他函数进行操作的函数,方法是将它们作为参数或将它们作为结果返回。这允许更抽象和简洁的代码,从而提高可读性和可维护性。高阶函数可以帮助减少代码重复和复杂性,使您的代码更高效且更易于调试。
PHP中的普通函数执行特定任务并返回结果。另一方面,高阶函数可以将一个或多个函数作为参数,将函数作为结果返回,或者同时具备这两个特性。这允许在代码中实现更大的灵活性和抽象性,使您可以用更少的代码创建更复杂的功能。
当然,让我们考虑PHP中的array_map
函数,它是一个高阶函数。它将回调函数和数组作为参数,将回调函数应用于数组的每个元素,并返回一个包含结果的新数组。
// 我们将传递给高阶函数的简单用户定义函数 function echoHelloWorld() { echo "Hello World!"; } // 接受函数作为输入并调用它的高阶函数 function higherOrderFunction(callable $func) { $func(); } // 调用我们的高阶函数并传入我们的echoHelloWorld()函数。 // 请注意,我们只将名称作为字符串传递,没有括号。 // 这将输出 "Hello World!" higherOrderFunction('echoHelloWorld');
PHP中的高阶函数提供多种好处。它们允许更抽象和简洁的代码,这可以提高可读性和可维护性。它们还可以帮助减少代码重复和复杂性,使您的代码更高效且更易于调试。此外,高阶函数可以促进代码重用,因为您可以将不同的函数传递给高阶函数以实现不同的行为。
虽然高阶函数提供了许多好处,但它们也可能有一些缺点。它们有时会导致代码难以理解和调试,尤其对于不熟悉函数式编程概念的开发人员而言。此外,使用高阶函数有时会导致性能开销,因为它们通常涉及创建和调用其他函数。
在PHP中创建您自己的高阶函数,需要定义一个函数,该函数可以接受一个或多个函数作为参数,将函数作为结果返回,或者同时具备这两个特性。这是一个简单的示例,它将函数作为参数并将其应用于值的简单高阶函数:
// 返回PHP中名为trim()的现有函数。注意它是一个简单的字符串,没有括号。 function trimMessage1() { return 'trim'; } // 这是一个使用匿名内联函数的示例 function trimMessage2() { return function($text) { return trim($text); }; } // 返回'trim'函数 $trim1 = trimMessage1(); // 使用我们的字符串进行修剪并调用它 echo $trim1(' hello world '); // 返回内部调用'trim'的匿名函数 $trim2 = trimMessage1(); // 使用我们的字符串进行修剪并再次调用它 echo $trim2(' hello world ');
是的,PHP中的高阶函数可以返回多个函数。这通常通过返回函数数组来完成。但是,请记住,每个返回的函数都有其自己的作用域,并且不会与其他返回的函数共享变量。
是的,PHP中的高阶函数可以接受来自不同作用域的函数。这是因为PHP支持一等函数,这意味着函数可以作为参数传递给其他函数,由其他函数返回,并分配给变量。
PHP中的闭包是一种匿名函数,可以捕获周围作用域中的变量。它们通常与高阶函数一起使用,因为它们允许创建访问比其参数更多数据的函数。这对于创建更灵活和可重用的代码非常有用。
是的,PHP提供了一些内置的高阶函数。一些示例包括array_map
、array_filter
和array_reduce
。这些函数将回调函数作为参数,并以各种方式将其应用于数组的元素。
以上是PHP中的功能编程:高阶功能的详细内容。更多信息请关注PHP中文网其他相关文章!