php 编程规范 函数_函数式编程和PHP

php 编程规范 函数

Many programmers like to talk about functional programming, but if you ask them if they’ve ever done it, most of their replies will be “No”. The reason is quite simple: we are taught to think in an imperative manner when we first start learning to program, in terms of flow charts and steps to be followed in the program. So in this article I’ll explain some important concepts to functional programming and how to write functional code in PHP.

许多程序员喜欢谈论函数式编程,但是如果您问他们是否曾经做过函数编程,他们的大多数答复将是“否”。 原因很简单:当我们第一次开始学习编程时,我们被教导必须以必要的方式进行思考,包括流程图和程序中要遵循的步骤。 因此,在本文中,我将解释函数式编程的一些重要概念以及如何用PHP编写函数式代码。

函数式编程的重要概念 (Important Concepts of Functional Programming)

Starting with the jargon, Wikipedia defines functional programming as “a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data.” In functional programming, functions are treated as first-class citizens, whereas in imperative programming we are mostly concerned with the data and the steps to alter it to reach the desired result.

从术语开始, 维基百科将功能编程定义为“一种编程范例,将计算视为对数学函数的评估,并避免了状态和可变数据。” 在函数式编程中,函数被视为一等公民,而在命令式编程中,我们最关心的是数据及其更改数据以获得所需结果的步骤。

When we say functions are first-class, it means we can use functions just as we use values in imperative programming. They can be passed as an argument to a function, defined inside another function, and can even be returned as a result. In other words, “functions are values”.

当我们说函数是一流的时,这意味着我们可以像在命令式编程中使用值一样使用函数。 它们可以作为参数传递给在另一个函数内部定义的函数,甚至可以作为结果返回。 换句话说,“功能就是价值”。

We’ll come back to this again later, but there are many other important concepts of functional programming. To mention a few:

稍后我们将再次讨论,但是函数编程还有许多其他重要的概念。 列举一些:

不变性 (Immutability)

Immutability is the behavior that a value of a variable cannot be changed once it is defined. Different languages have different ways of achieving this; in PHP, for instance, the only way to make a variable immutable is to define it as a constant.

不变性是指变量的值一旦定义就无法更改的行为。 不同的语言具有不同的实现方式; 例如,在PHP中,使变量不可变的唯一方法是将其定义为常量。

递归 (Recursion)

Recursion is also very prominent in functional programming. In imperative programming, we can use looping constructs like for and foreach when we need to manipulate collections or arrays, walking through each element and keeping a temporary variable to hold the current value. But because of immutability, this approach is not possible in functional programming. Recurssion is the answer because such book keeping is done implicitly with the call stack.

递归在函数式编程中也非常突出。 在命令式编程中,当我们需要操纵集合或数组,遍历每个元素并保留一个临时变量来保存当前值时,可以使用forforeach类的循环结构。 但是由于不变性,这种方法在函数式编程中是不可能的。 递归就是答案,因为这种记账是通过调用堆栈隐式完成的。

Suppose we want to write a function to find the sum of all elements in an array (forget that array_sum() exists for the time being). In a functional style, we would write:

假设我们要编写一个函数来查找数组中所有元素的总和(忘记array_sum()暂时存在)。 用一种功能风格,我们可以这样写:

<?php
function sum($array) {
    if (empty($array))
        return 0;
    else
        return $array[0] + sum(array_slice($array, 1));
}

$total = sum(array(1, 2, 3)); // 6

An empty list will return 0, which is our base condition. For an array with more than one value, it will return the results of adding the first element with the recursive sum of all other elements.

一个空列表将返回0,这是我们的基本条件。 对于具有多个值的数组,它将返回将第一个元素与所有其他元素的递归和相加的结果。

纯函数和参照透明 (Pure Functions and Referential Transparency)

A function is said to be free from side effects if it does not change the value of an object outside itself, such as a global or static variable, and does not have any I/O effects like writing into file, database, and so on. Such functions are otherwise called pure functions.

如果函数不更改自身外部对象的值(例如全局变量或静态变量)并且不具有任何I / O效果(如写入文件,数据库等),则称该函数没有副作用。 。 这样的函数在其他方面称为纯函数。

The output of a pure function will always be the same for a given set of arguments, which leads to another property called referential transparency. When a function is referentially transparent, we can replace that function with its value without affecting the behavior of the program. All mathematical functions are pure functions, whereas date functions, rand(), etc. are impure.

对于给定的一组参数,纯函数的输出将始终相同,这将导致另一个称为引用透明性的属性。 当一个函数是参照透明的时,我们可以用其值替换该函数而不会影响程序的行为。 所有数学函数都是纯函数,而日期函数, rand()等是不纯的。

高阶函数 (Higher Order Functions)

The concepts above can be achieved in almost any programming language, but first class functions and higher order functions are the two most distinguishing features of functional programming. I explained that first class functions means that functions can be treated as values. Higher order functions are functions that can take functions as arguments and can return a function as their result. Two important features were added relatively recently which enabled us to write higher order functions in PHP: lambdas and closures.

上面的概念几乎可以用任何一种编程语言来实现,但是一流的函数和高阶函数是函数式编程的两个最明显的特征。 我解释说,一流的函数意味着可以将函数视为值。 高阶函数是可以将函数作为参数并可以返回函数作为结果的函数。 相对较新地添加了两个重要的功能,它们使我们能够用PHP编写更高阶的函数:lambda和闭包。

Lambda函数 (Lambda Functions)

A lambda function (also known as anonymous function) is nothing but a function that has no name. When we define an anonymous function, a reference to the function is returned which is stored in a variable for later use. We use this variable to call the function whenever it’s needed.

Lambda函数(也称为匿名函数)不过是一个没有名称的函数。 当我们定义匿名函数时,将返回对该函数的引用,该引用存储在变量中,以备后用。 我们在需要时使用此变量来调用该函数。

This concept has been adopted in many different languages. In fact, you’re probably using lambda functions in your day-to-day JavaScript programming, passing them as callback functions for different user interactions and Ajax calls.

这个概念已被许多不同的语言采用。 实际上,您可能在日常JavaScript编程中使用了lambda函数,并将它们作为回调函数传递给不同的用户交互和Ajax调用。

$("#myButton").click(function () {
    // do something
});

This piece of code is so simple and easy to understand, which might make us forget its functional aspect.

这段代码是如此简单和易于理解,这可能使我们忘记其功能方面。

PHP introduced this awesome feature in version 5.3, which lets us write PHP code in a similar fashion:

PHP在5.3版中引入了这个很棒的功能,它使我们能够以类似的方式编写PHP代码:

<?php
$square = function ($arg) {
    return $arg * $arg;
};

$value = $square(2); // 4

When talking about functions, and anonymous functions in particular, its important to understand how variable scope is handled. JavaScript, for example, allows you to access a variable from an outer scope inside the lambda, whereas PHP does not. Inside the lambda is its own scope, just as with regular PHP functions.

在讨论函数(尤其是匿名函数)时,了解如何处理变量作用域非常重要。 例如,JavaScript允许您从lambda的外部范围访问变量,而PHP则不允许。 就像常规PHP函数一样,lambda里面有自己的作用域。

关闭 (Closures)

Sometimes you’ll want to reference a variable from the parent scope inside your function. Closures are similar to lambda functions with the minor difference that you can access variables from an outer scope. We can use “reach out” and bind an outer variable using PHP’s use keyword, also introduced in PHP 5.3.

有时,您可能想从函数内部的父作用域中引用变量。 闭包与lambda函数类似,不同之处在于可以从外部范围访问变量。 我们可以使用“触及”并使用PHP的use关键字(也在PHP 5.3中引入)绑定外部变量。

<?php
$rate = .12;

$findInterest = function ($value) use ($rate) {
    return $value * $rate;
};

$interest = $findInterest(100);

In this case we don’t pass the interest rate each time we call the function. Instead, we’ve defined it outside and made it available inside the function with the use keyword.

在这种情况下,我们不会在每次调用函数时都通过利率。 相反,我们在外部定义了它,并use关键字使其在函数内部可用。

部分函数和咖喱 (Partial Functions and Currying)

A partial function, simply put, is a function created from an existing function by partially applying its arguments. You only need to pass the remaining arguments when you call the created function.

简单地说,部分函数是通过部分应用其参数从现有函数创建的函数。 您只需在调用创建的函数时传递其余参数即可。

We can create partial functions in PHP with the use of closures. Here’s an example to find the volume of a box given its length, width and height. All arguments are optional; if you don’t supply all of the arguments, the function will return another function to accept the necessary values that remain.

我们可以使用闭包在PHP中创建部分函数。 这是一个根据箱子的长度,宽度和高度来查找其体积的示例。 所有参数都是可选的; 如果不提供所有参数,则该函数将返回另一个函数以接受剩余的必要值。

<?php
$volume = function ($length = 0, $width = 0, $height = 0) use (&$volume) {
    $args = func_get_args();
    $numArgs = func_num_args();
    if ($numArgs == 3) {
        return $length * $width * $height;
    }
    else if ($numArgs < 3) {
        return function() use(&$volume, $args) {
            $newArgs = array_merge($args, func_get_args());
            return call_user_func_array($volume, $newArgs);
        };
    }
    else {
        throw new BadFunctionCallException("Too many arguments");
    }
};

All of the parameters are optional. First a check is made to determine whether the caller passed all arguments. In that case, we can directly return the volume by multiplying length, width and height. If the number of arguments is less than the parameters, a new function is returned to find the volume “pre-seeded” with the given arguments.

所有参数都是可选的。 首先进行检查以确定调用方是否传递了所有参数。 在这种情况下,我们可以直接乘以长度,宽度和高度来返回体积。 如果参数数量小于参数,则返回一个新函数以查找具有给定参数的“预播种”卷。

Now suppose that most of the time we’re finding the volume of box with a fixed length, say 10. This can be easily done by passing 10 as the first argument, or we could create the partial function by fixing 10 as the first argument and then only ask for the remaining values.

现在假设大多数情况下,我们发现固定长度的box的体积为10。这可以通过将10作为第一个参数传递来轻松完成,或者我们可以通过将10作为第一个参数固定来创建偏函数。然后只要求剩余的值。

<?php
$standardVolume = $volume(10);

$vol = $standardVolume(5, 5); // 250

Currying is a special case of partial functions where you convert a function that takes multiple arguments into to multiple functions that will each take a single argument. For example, something like f(x,y,z) to f(x)(y)(z) (although PHP syntax doesn’t allow nesting of function calls like this). Timothy Boronczyk has written an excellent article on currying with a practical example if you’re interested in seeing more.

Currying是部分函数的一种特殊情况,在这种情况下,您将一个带有多个参数的函数转换为多个每个都带有一个参数的函数。 例如,从f(x,y,z)f(x)(y)(z)之类的东西 (尽管PHP语法不允许嵌套这样的函数调用)。 如果您有兴趣了解更多内容, Timothy Boronczyk撰写了一篇关于 curring的出色文章,并提供了一个实际示例。

的优点和缺点 (Advantages and Disadvantages)

There are many practical uses of functional programming features in PHP. For instance, lambda functions are widely used when working with callbacks. Using the Slim framework, for example, you can define a route like this:

PHP中有许多实用的功能编程功能用法。 例如,使用回调函数时,lambda函数被广泛使用。 例如,使用Slim框架,您可以定义以下路线:

<?php
$app = new SlimSlim();
$app->get("/home", function () {
    // show home page
});

Slim invokes the callback function when the request URL matches this route. Vance Lucas wrote about some other interesting use cases of Lambda functions a while back.

当请求URL与此路由匹配时,Slim调用回调函数。 万斯·卢卡斯(Vance Lucas)不久前还写了Lambda函数其他一些有趣用例

Safe programming is encouraged by avoiding state and mutable data. In functional programming you should write functions that do exactly one thing each and do not cause any side effects. The paradigm’s emphasis on modularity and conciseness of functions can make its easier to reason about your program in terms of different, small sub programs as well.

通过避免状态和可变数据来鼓励安全编程。 在函数式编程中,您应该编写函数,每个函数仅做一件事,并且不会引起任何副作用。 该范式强调模块的模块化和功能的简洁性,也可以使其更容易根据不同的小型子程序来推理您的程序。

Functional programming can also help you write code that focuses what you want to achieve instead of explicitly managing the incidentals in the process (compare recursion with having to manage loop counter variables).

函数式编程还可以帮助您编写专注于您要实现的目标的代码,而不是在过程中显式管理杂项(将递归与必须管理循环计数器变量进行比较)。

But keep in mind however that some of the advantages traditionally associated with functional programming are not applicable to PHP as it’s not designed to be a functional programming language. For example, side-effect-free functions lend well to parallel processing, but PHP scripts are not run in this manner.

但是请记住,传统上与​​函数式编程相关联的某些优势不适用于PHP,因为它并非设计为函数式编程语言。 例如,无副作用的函数很适合并行处理,但是PHP脚本不是以这种方式运行的。

It’s not always easy to calculate the cost of recursion and lazy functions, either, and there can be significant performance issues due to the internal overhead. Sometimes it makes more sense to write programs in terms of mutability for better efficiency.

同样,计算递归和惰性函数的成本也不总是那么容易,并且由于内部开销而可能会导致严重的性能问题。 有时,出于可变性的考虑,编写程序更有意义。

Perhaps the biggest disadvantage of functional programming is its steep learning curve for those trained in an imperative manner. But over all, functional programming is interesting, and learning it will give you the tools to think about old problems in a new light, helping you to grow as a programmer. It’s not a one-size fits all solution, but it can be applied as appropriate for cleaner, more eloquent PHP code.

函数式编程的最大缺点也许是对以命令式方式培训的人员的学习曲线陡峭。 但总的来说,函数式编程很有趣,学习函数式编程将为您提供新的角度思考旧问题的工具,从而帮助您成长为一名程序员。 它不是一种千篇一律的解决方案,但可以适当地用于更简洁,更精通PHP代码。

摘要 (Summary)

Functional programming is more than just a programming paradigm; it’s a way of thinking and reasoning about your program. If you can think functionally, you can do functional programming in almost any language.

函数式编程不仅仅是编程范例; 这是对程序进行思考和推理的一种方式。 如果您可以从功能上进行思考,则可以使用几乎所有语言进行功能编程。

In this article we discussed the basics of functional programming, leveraging features of PHP to write provide their examples. Although, the example given in this article may not be practically useful to you, you’ll find many situations where the functional style can significantly improve the quality of code you are writing. Try to find such cases, think functionally, and have fun!

在本文中,我们讨论了函数式编程的基础,并利用PHP的功能编写了示例。 尽管本文给出的示例可能对您实际上没有用,但是您会发现许多情况下,函数样式可以显着提高所编写代码的质量。 尝试找到这种情况,从功能上思考,然后玩得开心!

Image via Fotolia

图片来自Fotolia

翻译自: https://www.sitepoint.com/functional-programming-and-php/

php 编程规范 函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值