成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

PHP函數(shù)式編程的初步認(rèn)識(shí)

wwq0327 / 3039人閱讀

摘要:函數(shù)式編程不是一個(gè)框架或工具,而是一種編寫代碼的方式。函數(shù)式編程首先是一個(gè)聲明式編程范例。舉個(gè)例子純函數(shù)函數(shù)式編程基于的前提是您將基于純函數(shù)構(gòu)建不可變的程序作為業(yè)務(wù)邏輯的構(gòu)建塊。

最近朋友推薦這本書:Functional PHP ,很多對(duì)于程序設(shè)計(jì)方面的思路值得多思考和借鑒。函數(shù)式編程不是一個(gè)框架或工具,而是一種編寫代碼的方式。FP 是一種軟件開發(fā)風(fēng)格,主要強(qiáng)調(diào)功能的使用,個(gè)人覺得對(duì)于重構(gòu)代碼很有幫助。書中也談到了例如 PHP5.3 中引入的閉包函數(shù)和高階函數(shù),在實(shí)際開發(fā)過程中善于活學(xué)活用也是函數(shù)式的靈魂所在。

PHP 新版本的解讀

增加了嚴(yán)格的鍵入和標(biāo)量類型聲明類型聲明允許你用合適的類或標(biāo)量類型( boolean,integer,string,MyClass 等)限定任何函數(shù)參數(shù)。這些在PHP 5中被部分支持為“類型提示”,但沒有標(biāo)量支持。在PHP 7中,你也可以聲明函數(shù)返回值的類型。
作為一種動(dòng)態(tài)語言,PHP 將總是試圖將錯(cuò)誤類型的值強(qiáng)制轉(zhuǎn)換為期望的標(biāo)量類型。
例如,當(dāng)給定一個(gè)字符串時(shí),需要一個(gè)整數(shù)參數(shù)的函數(shù)將強(qiáng)制該值為一個(gè)整數(shù),文件頂部引用強(qiáng)制類型檢測(cè)模式

declare(strict_types=1);

參數(shù)異常會(huì)拋出如下錯(cuò)誤e

PHP Warning:  Uncaught TypeError: Argument 1 passed to increment() must be of the type integer, string given...
聲明性編碼

感覺翻譯后的理解很模糊,看例子可能會(huì)更加清晰透徹一點(diǎn)。“函數(shù)式編程首先是一個(gè)聲明式編程范例。這意味著它們表達(dá)了操作的邏輯連接,而不會(huì)泄露它們是如何實(shí)現(xiàn)的,或者數(shù)據(jù)如何實(shí)際流經(jīng)它們,它著重于使用表達(dá)式來描述程序的邏輯是什么”

在 PHP 中,聲明性代碼是使用高階函數(shù)來實(shí)現(xiàn)的,個(gè)人覺得作者的意思還是靈活運(yùn)用系統(tǒng)內(nèi)置函數(shù)處理邏輯,放棄復(fù)雜而不簡潔的邏輯控制,代碼越復(fù)雜,重構(gòu)越麻煩,bug率更高。一個(gè)簡單的例子走一個(gè)。

// method 1

$array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for($i = 0; $i < count($array); $i++) {
    $array[$i] = pow($array[$i], 2);
}

print_r($array); //-> [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

// method 2
$square = function (int $num): int {
    return pow($num, 2);
};

print_r(array_map($square, $array))

// q: 結(jié)果累加
function add(float $a, float $b): float {
     return $a + $b;
}

print_r(array_reduce(array_map($square, $array), "add")); //-> 285
設(shè)計(jì)為不變性和無狀態(tài)

例如是上面的例子中使用的 array_map ,好處在于它不可變,也就是說不會(huì)改變?cè)紨?shù)組的內(nèi)容,使用不可變變量進(jìn)行編碼好處如下:

程序出現(xiàn)異常的主要原因之一是對(duì)象的狀態(tài)無意中改變,或者其引用變?yōu)榭?。不可變?duì)象可以傳遞給任何函數(shù),它們的狀態(tài)將始終保持不變。

不可變的數(shù)據(jù)結(jié)構(gòu)在共享內(nèi)存多線程應(yīng)用程序中非常重要。在本書中,我們不會(huì)多談關(guān)于并發(fā)處理的問題,因?yàn)?PHP 進(jìn)程大部分是孤立運(yùn)行的。現(xiàn)在,無論是否設(shè)計(jì)并行性,無狀態(tài)對(duì)象都是在許多常見PHP部署中廣泛使用的模式。例如,作為最佳實(shí)踐,Symfony 服務(wù)(或服務(wù)對(duì)象)應(yīng)該始終是無狀態(tài)的。一個(gè)服務(wù)不應(yīng)該持續(xù)任何狀態(tài),并提供一組臨時(shí)函數(shù),它們將處理它所在的域,執(zhí)行某種業(yè)務(wù)邏輯的計(jì)算,并返回結(jié)果。

PHP 對(duì)于不可變變量的支持很差,實(shí)際開發(fā)過程中使用常量定義 define const 關(guān)鍵字。對(duì)于 define 和 const 的比較。const 在編譯時(shí)定義,這意味著編譯器可以聰明地存儲(chǔ)它們,但是你不能有條件地聲明。用 define 聲明的常量是多功能和動(dòng)態(tài)的。因?yàn)榫幾g器不會(huì)嘗試為它們分配空間,直到它真正看到它們。defined($name) 在使用它的值之前,你應(yīng)該經(jīng)常檢查是否定義了一個(gè)常量 constant($name)。舉個(gè)例子

// error : throw exception
if () {
    const C1 = "FOO";
} else {
    const C2 = "BAR";
}

// ok normal
if () {
    define("C1", "FOO")
} else {
    define("C2", "BAR")
}
純函數(shù)

函數(shù)式編程基于的前提是您將基于純函數(shù)構(gòu)建不可變的程序作為業(yè)務(wù)邏輯的構(gòu)建塊。

高階 PHP

關(guān)于高階函數(shù)和閉包本書都會(huì)提到,高階函數(shù)被定義為可以接受其他函數(shù)作為參數(shù)或返回其他函數(shù)的函數(shù)。當(dāng)然函數(shù)可以分配給變量。

PHP 中的函數(shù)可以像對(duì)象一樣進(jìn)行操作。事實(shí)上,如果你要檢查一個(gè)函數(shù)的類型,你會(huì)發(fā)現(xiàn)它們是Closure
的實(shí)例。將一個(gè)函數(shù)賦予給一個(gè)變量這個(gè)在實(shí)際應(yīng)用中很常見。例如下面的例子

$str = function (string $str1, string $str2) {
    return $str1 . " " . $str2;
}

$str("hello", "word"); // output hello word;

is_callable($str) // 1

這個(gè)代碼使用匿名函數(shù)(RHS)并將其分配給變量 $str(LHS)。或者,您可以使用 is_callable() 來檢查是否存在函數(shù)變量

函數(shù)也可以從其他函數(shù)返回。這是創(chuàng)建函數(shù)族的非常有用的技巧。

function concatWith(string $a): callable {
    return function (string $b) use ($a): string {
        return $a . $b;
};
}

$helloWith = concatWith("Hello");
$helloWith("World"); // output -> "Hello World"

提供函數(shù)作為參數(shù), 創(chuàng)建了一個(gè)簡單的函數(shù),它接受一個(gè)可調(diào)用的函數(shù)并將其應(yīng)用于其他參數(shù)

function apply(callable $operator, $a, $b) {
    return $operator($a, $b);
}

$add = function (float $a, float $b): float {
    return $a + $b;
};

apply($add, 1, 2); // output -> 3

// or power

function apply(callable $operator): callable {
    return function($a, $b) use ($operator) {
        return $operator($a, $b);
    };
}

apply($add)(5, 5); //output -> 10

$adder = apply($add);

$adder(5, 5) // output -> 10

遇到另外一種情況,也就是兩個(gè)數(shù)相除分母不能為0,這個(gè)時(shí)候構(gòu)建一個(gè)空檢查函數(shù)會(huì)比較好,時(shí)刻檢查變量的值是個(gè)好習(xí)慣。

function safeDivide(float $a, float $b): float {   
    return empty($b) ? NAN : $a / $b;
}

apply($safeDivide)(5, 0); //-> NAN

$result = apply($safeDivide)(5, 0);
if(!is_nan($result)) {
    return $result;
} else {
    Log::warning("Math error occurred! Division by zero!");
}

“這種方法避免了拋出一個(gè)異常?;叵胍幌聮伄惓5那闆r,它會(huì)導(dǎo)致程序堆棧展開和記錄寫入,但也不尊重代碼的局部性原則。尤其是它不服從空間地域性,它指出應(yīng)該依次執(zhí)行的相關(guān)陳述應(yīng)該相互靠近。這在 CPU 架構(gòu)上有更多的應(yīng)用,但也可以應(yīng)用于代碼設(shè)計(jì)?!边@種翻譯型的語句我還是日后在理解吧,說不定有一天就豁然開朗了,畢竟這是一條很遙遠(yuǎn)的路。

PHP 還通過可調(diào)用的對(duì)象將其提升到了一個(gè)新的水平?,F(xiàn)在,這不是一個(gè)真正的功能概念,但正確使用它可能是一個(gè)非常強(qiáng)大的技術(shù)。事實(shí)上,引擎蓋下的 PHP 匿名函數(shù)語法被編譯成一個(gè)類,并且有一個(gè)invoke() 方法。查資料的釋義就是調(diào)用函數(shù)的方式調(diào)用一個(gè)對(duì)象時(shí)的回應(yīng)方法

class Demo
{
    private $collect;

    public function __construct($num)
    {
        $this->collect = $num;
    }

    public function increment() : int {

        return ++$this->collect;
    }

    public function __invoke() {
        return $this->increment();
    }
}

$demo = new Demo(1);

echo $demo(); // output -> 2
使用容器改善api

使用包裝來控制對(duì)特定變量的訪問并提供額外的行為。先看下例子中的這個(gè) class ,下面的例子擴(kuò)展性較強(qiáng)

class Container {
    private $_value;

    private function __construct($value) {        
        $this->_value = $value;                
    }

    // Unit function
    public static function of($val) {            
        return new static($val);
    }

    // Map function
    public function map(callable $f) {
        return static::of(call_user_func($f, $this->_value));
    }

    // Print out the container
    public function __toString(): string {
        return "Container[ {$this->_value} ]";  
    }

    // Deference container
    public function __invoke() {
        return $this->_value;
    }
}
function container_map(callable $f, Container $c): Container {
    return $c->map($f);
}
$c = Container::of("")->map("htmlspecialchars")->map("strtolower");

$c; //output-> Container[  ]
關(guān)閉

在 PHP 5.4+之后,PHP中的所有函數(shù)都是從 Closure 類創(chuàng)建的對(duì)象。使用RFC可以使代碼更加簡潔明了

function addTo($a) {
    return function ($b) use ($a) {
           return $a + $b;
    };
}

$filter = function (callable $f): Container {
    return Container::of(call_user_func($f, $this->_value) ? $this->_value : 0);
};

$wrappedInput = Container::of(2);

$validatableContainer = $filter->bindTo($wrappedInput, Container);

$validatableContainer("is_numeric")->map(addTo(40)); // output-> 42

$wrappedInput = Container::of("abc); $validatableContainer("is_numeric")->map(addTo(40)); // output-> 40
說明

關(guān)于這本書的詳細(xì)內(nèi)容和例子戳鏈接 Functional PHP,關(guān)于 函數(shù)式編程的 composer 包 Functional PHP: Functional primitives for PHP

{
    "require": {
        "lstrojny/functional-php": "~1.2"
    }
}

本質(zhì)上這本書我還沒有看完,翻譯起來很多地方確實(shí)詞不達(dá)意,我還是根據(jù)實(shí)際的舉例逐個(gè)去理解的,此文章后續(xù)還會(huì)繼續(xù)補(bǔ)充和追加學(xué)習(xí)心得。 Go PHP!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/26215.html

相關(guān)文章

  • 初步認(rèn)識(shí)函數(shù)

    摘要:函數(shù)對(duì)象連接到。好處有助于確保全局名字空間的純凈性私有性保留了自己的函數(shù),不為外部應(yīng)用程序所用返回自己的函數(shù)函數(shù)始終有一個(gè)返回值,即便不是顯示返回,它們會(huì)隱式返回一個(gè)。 函數(shù) 概念: 函數(shù)包含一組語句,它們是javaScript基礎(chǔ)模塊單元,用于代碼復(fù)用、信息隱藏和組合調(diào)用。用于指定對(duì)象的行為。 函數(shù)對(duì)象: javascrtipt中的函數(shù)就是對(duì)象。對(duì)象是‘名/值’對(duì)的集合并擁有一個(gè)連...

    Rango 評(píng)論0 收藏0
  • [零基礎(chǔ)學(xué)python]關(guān)于類初步認(rèn)識(shí)

    摘要:反對(duì)者在某些領(lǐng)域?qū)Υ擞枰苑裾J(rèn)。下面再引用一段來自維基百科中關(guān)于的歷史。類的更嚴(yán)格的定義是由某種特定的元數(shù)據(jù)所組成的內(nèi)聚的包。類還可以有運(yùn)行時(shí)表示形式元對(duì)象,它為操作與類相關(guān)的元數(shù)據(jù)提供了運(yùn)行時(shí)支持。 在開始部分,請(qǐng)看官非常非常耐心地閱讀下面幾個(gè)枯燥的術(shù)語解釋,本來這不符合本教程的風(fēng)格,但是,請(qǐng)看官諒解,因?yàn)榱形粚硪欢ㄒ喿x枯燥的東西的。這些枯燥的屬于解釋,均來自維基百科。 1、問題...

    王巖威 評(píng)論0 收藏0
  • 從零帶你入門Socket編程

    摘要:網(wǎng)絡(luò)編程就是如何在程序中實(shí)現(xiàn)兩臺(tái)計(jì)算機(jī)的通信。而網(wǎng)絡(luò)編程最終要開發(fā)出來的應(yīng)用大多數(shù)為支持各種協(xié)議的服務(wù)器,比如服務(wù)器服務(wù)器或者是基于自定義的協(xié)議實(shí)現(xiàn)的服務(wù)。在開始編碼之前,首先介紹一下協(xié)議棧上圖是我從網(wǎng)絡(luò)編程這本書拍下來的。 相信大部分的初中級(jí)PHP程序員平時(shí)寫的業(yè)務(wù)代碼占絕大多數(shù),寫厭了平時(shí)的增刪改查,何不體驗(yàn)體驗(yàn)網(wǎng)絡(luò)編程的魅力呢。 學(xué)習(xí)網(wǎng)絡(luò)編程能夠很好的理解一些底層的網(wǎng)絡(luò)通信,比如...

    glumes 評(píng)論0 收藏0
  • 函數(shù)編程 - 容器(container)

    摘要:函子上面容器上定義了方法,的定義也類似是實(shí)現(xiàn)了函數(shù)并遵守一些特定規(guī)則的容器類型。不同類型的函子容器在處理內(nèi)部值時(shí),經(jīng)常遇到傳入?yún)?shù)異常的情況的情況,檢查值的合理性就非常重要。函子保證在調(diào)用傳入的函數(shù)之前,檢查值是否為空。 最近一直在學(xué)習(xí)函數(shù)式編程,前面介紹了函數(shù)式編程中非常重要的兩個(gè)運(yùn)算函數(shù)柯里化 和 函數(shù)組合,下文出現(xiàn)的curry 和 compose函數(shù)可以從前兩篇文章中找到。它們都...

    Anchorer 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<