首页 > 后端开发 > php教程 > PHP中的传感器变得容易

PHP中的传感器变得容易

Christopher Nolan
发布: 2025-02-15 11:36:11
原创
919 人浏览过

深入PHP函数式编程:探秘Transducers

你可能听说过函数式编程和高阶函数,但你了解Transducers吗?本文将带你探索这个强大的数据转换工具。

Transducers in PHP Made Easy

核心要点:

  • Transducers源于Clojure,由Michael Dowling移植到PHP,是一种构建可重用算法转换的强大方法。它们是接受一个约简函数并返回另一个约简函数的函数。
  • PHP的Transducers包允许以多种方式转换数据,例如将名称的首字母大写或从用户列表中删除未成年人。转换可以组合成单个Transducer以供重用。
  • Transducer中的约简函数接收一个值作为参数,并返回一个包含三个元素的约简函数数组:“init”(初始值)、“result”(最终结果)和“step”(约简逻辑)。
  • Transducers的优势在于它将数据转换过程与实际数据源分离,使代码更模块化、更易于维护。它们允许创建可重用的软件组件,可用于任何数据源。然而,由于其函数式编程的根源,它们可能比传统的PHP函数更复杂。

Transducers定义

要理解Transducers,首先需要了解约简器(Reducers)。引用Rich Hickey的话:

一个约简函数正是你传递给reduce的函数类型——它接收迄今为止的结果和一个新的输入,并返回下一个迄今为止的结果。

一个Transducer是一个函数,它接收一个约简函数并返回另一个约简函数。

Transducers最初由Rich Hickey引入Clojure,并由Michael Dowling移植到PHP。Transducers是构建可在多种情况下重用的算法转换的强大方法。本文将通过一系列实际示例来探讨其用途。

示例

在继续之前,我们需要通过Composer安装Transducers包。

composer require mtdowling/transducers
登录后复制
登录后复制
登录后复制

我们将为以下示例使用一个简单的User类。

class User
{
    public $id;
    public $name;
    public $age;

    public function __construct($id, $name, $age)
    {
        $this->id = $id;
        $this->name = $name;
        $this->age = $age;
    }

    public function __toString()
    {
        return sprintf("\n%d - %s - %d", $this->id, $this->name, $this->age);
    }
}

// 示例数据
$data = [
    new User(1, "younes", 24),
    new User(2, "youssef", 26),
    new User(3, "hamza", 25),
    new User(4, "ismail", 17),
];
登录后复制
登录后复制
use Transducers as t;

$uppercase = t\map(function($user) { 
    return new User($user->id, ucfirst($user->name), $user->age); 
});

$result = t\xform($data, $uppercase);

var_dump($result);
登录后复制
登录后复制

map函数类似于PHP的array_map函数:我们传递一个可调用函数,在本例中,它将把用户名首字母大写。

我们使用xform函数应用我们的uppercase Transducer。它将我们的数据作为第一个参数,Transducer作为第二个参数。

// 输出
array(4) {
  [0]=>
  object(User)#14 (3) {
    ["id"]=>
    int(1)
    ["name"]=>
    string(6) "Younes"
    ["age"]=>
    int(24)
  }
  [1]=>
  object(User)#15 (3) {
    ["id"]=>
    int(2)
    ["name"]=>
    string(7) "Youssef"
    ["age"]=>
    int(26)
  }
  [2]=>
  object(User)#16 (3) {
    ["id"]=>
    int(3)
    ["name"]=>
    string(5) "Hamza"
    ["age"]=>
    int(25)
  }
  [3]=>
  object(User)#17 (3) {
    ["id"]=>
    int(4)
    ["name"]=>
    string(6) "Ismail"
    ["age"]=>
    int(17)
  }
}
登录后复制
登录后复制

xform返回与数据参数相同类型的值(在本例中为数组)。如果严格需要输出数组,我们也可以使用to_array

// ...
$result = t\to_array($data, $uppercase);
// ...
登录后复制
登录后复制

我们也可以使用to_string将输出转换为字符串,或者使用into($target, $coll, callable $xf)将输出转换为特定类型。更多细节请查看文档。

composer require mtdowling/transducers
登录后复制
登录后复制
登录后复制
class User
{
    public $id;
    public $name;
    public $age;

    public function __construct($id, $name, $age)
    {
        $this->id = $id;
        $this->name = $name;
        $this->age = $age;
    }

    public function __toString()
    {
        return sprintf("\n%d - %s - %d", $this->id, $this->name, $this->age);
    }
}

// 示例数据
$data = [
    new User(1, "younes", 24),
    new User(2, "youssef", 26),
    new User(3, "hamza", 25),
    new User(4, "ismail", 17),
];
登录后复制
登录后复制

Transducers最棒的部分是我们可以将多个转换组合成一个Transducer。例如,让我们将用户名的首字母大写并删除未成年人。

use Transducers as t;

$uppercase = t\map(function($user) { 
    return new User($user->id, ucfirst($user->name), $user->age); 
});

$result = t\xform($data, $uppercase);

var_dump($result);
登录后复制
登录后复制

filter函数类似于PHP的array_filter函数。comp函数从Transducer列表创建一个Transducer,在本例中为uppercase(使用map)和removeMinors(使用filter)。

// 输出
array(4) {
  [0]=>
  object(User)#14 (3) {
    ["id"]=>
    int(1)
    ["name"]=>
    string(6) "Younes"
    ["age"]=>
    int(24)
  }
  [1]=>
  object(User)#15 (3) {
    ["id"]=>
    int(2)
    ["name"]=>
    string(7) "Youssef"
    ["age"]=>
    int(26)
  }
  [2]=>
  object(User)#16 (3) {
    ["id"]=>
    int(3)
    ["name"]=>
    string(5) "Hamza"
    ["age"]=>
    int(25)
  }
  [3]=>
  object(User)#17 (3) {
    ["id"]=>
    int(4)
    ["name"]=>
    string(6) "Ismail"
    ["age"]=>
    int(17)
  }
}
登录后复制
登录后复制

现在我们有一个可重用的Transducer组合,我们可以随时使用它来根据此标准约简数据。查看文档以了解可用约简函数的列表。

创建Transducer

约简函数接收一个值作为参数,并返回一个约简函数数组,该数组必须包含三个元素:

  • init:返回Transducer初始值的函数。如果未提供初始值,则仅在第一次调用时调用。
  • resultresult函数用于根据调用栈构建最终结果。
  • step:这是你编写约简逻辑的地方——根据你的约简逻辑,你可能调用它零次或多次。

如果没有实际代码,这会变得非常混乱,因此让我们以take Transducer函数为例。它从数据数组顶部获取n个项目。

// ...
$result = t\to_array($data, $uppercase);
// ...
登录后复制
登录后复制
use Transducers as t;

$uppercase = t\map(function($user) { 
    return new User($user->id, ucfirst($user->name), $user->age); 
});

$result = t\to_string($data, $uppercase);

var_dump($result);
登录后复制

以下是take约简函数的源代码。

// 输出
string(64) "
1 - Younes - 24
2 - Youssef - 26
3 - Hamza - 25
4 - Ismail - 17"
登录后复制

take函数被多次调用,带有resultinput参数。每次调用时,它都会递减remaining变量并测试它是否小于零。在这种情况下,我们返回一个Reduced对象实例,这表示一个停止点。

我们的Transducer函数示例将从数据中删除空元素。使用前面关于Transducer工作原理的解释,我们可以访问$input变量,并决定是调用下一个step回调还是简单地返回值。

$uppercase = t\map(function($user) { 
    return new User($user->id, ucfirst($user->name), $user->age); 
});
$removeMinors = t\filter(function($user) { 
    return $user->age >= 18;
});

$comp = t\comp(
    $uppercase,
    $removeMinors
);

$result = t\to_string($data, $comp);

var_dump($result);
登录后复制

我们可以通过向我们的$data变量添加一些空项目来测试这一点。

// 输出
string(48) "
1 - Younes - 24
2 - Youssef - 26
3 - Hamza - 25"
登录后复制
// ....
$comp = t\comp(
    $uppercase,
    $removeMinors,
    t\take(2)
);

$result = t\to_string($data, $comp);

var_dump($result);
登录后复制

结论

在本文中,我们了解了函数式编程世界的一个新方面,称为Transducers。我们回顾了Transducers的目的,即使数据转换更容易。我们还回顾了一些示例,以更好地演示Transducers的价值。你现在在你的开发者工具箱中拥有了一个新的工具,或者至少对Transducer的概念有了更好的理解。

如果你对Transducers有任何疑问,可以在下面发表!

PHP中Transducers的常见问题

PHP中Transducers的基本概念是什么?

PHP中的Transducers是一种数据处理技术,允许你创建可组合和可重用的软件组件。它们本质上是接受一个约简器并返回一个新约简器的函数。这个概念借鉴自Clojure和JavaScript,并已适应PHP。Transducers允许你将数据转换过程与实际数据源分离,使你的代码更模块化、更易于维护。

Transducers与传统的PHP函数有何不同?

传统的PHP函数通常将获取数据和转换数据的过程结合在一起,这可能导致难以维护和重用的代码。另一方面,Transducers将这两个过程分开。这意味着你可以创建一个以特定方式转换数据的Transducer,然后将其与任何数据源一起使用,使你的代码更灵活、更可重用。

你能提供一个PHP中Transducer的示例吗?

当然,让我们考虑一个简单的示例。假设你有一个数字数组,并且你想将每个数字加1。你可以创建一个执行此操作的Transducer:

composer require mtdowling/transducers
登录后复制
登录后复制
登录后复制

然后,你可以将此Transducer与任何约简函数和数据源一起使用。

如何将Transducers与不同的数据源一起使用?

Transducers设计用于与任何数据源一起使用。这是因为它们在单个数据项级别运行,而不是在整个数据源级别运行。因此,你可以将Transducer与数组、数据库查询结果、来自网络连接的数据流等一起使用。唯一的要求是你的数据源必须能够与约简函数一起工作。

使用PHP中的Transducers有哪些好处?

Transducers提供了许多好处。它们允许你将数据转换过程与实际数据源分离,使你的代码更模块化、更易于维护。它们还允许你创建可重用的软件组件,可用于任何数据源。最后,因为Transducers操作单个数据项,所以在处理大型数据集时,它们可能比传统的PHP函数更高效。

使用PHP中的Transducers有哪些缺点?

虽然Transducers提供了许多好处,但它们也可能比传统的PHP函数更复杂。这是因为它们涉及函数式编程的概念,这些概念对一些PHP开发人员来说可能不熟悉。但是,一旦你理解了Transducers的工作原理,它们就可以成为编写干净、高效和可重用代码的强大工具。

Transducers可以与PHP框架一起使用吗?

是的,Transducers可以与任何PHP框架一起使用。它们是一种通用的数据处理技术,不依赖于任何特定的框架特性。但是,一些框架可能提供自己用于处理Transducers的实用程序,这可以使它们更容易使用。

如何学习更多关于PHP中Transducers的知识?

有很多资源可用于学习PHP中的Transducers。你可以从阅读网上的文章和教程开始,例如SitePoint上的文章。还有一些书籍和在线课程更深入地介绍了这个主题。最后,你可以尝试编写自己的Transducers并在你的PHP项目中使用它们。

Transducers在其他编程语言中使用吗?

是的,Transducers的概念起源于Clojure编程语言,此后已被其他几种语言采用,包括JavaScript和PHP。每种语言都以自己的方式实现Transducers,但基本概念是相同的。

我可以将Transducers与PHP内置的数组函数一起使用吗?

是的,你可以将Transducers与PHP内置的数组函数一起使用。但是,请记住,这些函数可能不如使用Transducer高效,尤其是在处理大型数组时。这是因为PHP的数组函数通常会创建新的数组,而Transducer可以在原地转换数据。

以上是PHP中的传感器变得容易的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板