国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

PHP函數(shù)式編程的初步認識

wwq0327 / 3019人閱讀

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

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

PHP 新版本的解讀

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

declare(strict_types=1);

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

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

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

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

// 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
設計為不變性和無狀態(tài)

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

程序出現(xiàn)異常的主要原因之一是對象的狀態(tài)無意中改變,或者其引用變?yōu)榭铡2豢勺儗ο罂梢詡鬟f給任何函數(shù),它們的狀態(tài)將始終保持不變。

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

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

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

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

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

高階 PHP

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

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

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

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

is_callable($str) // 1

這個代碼使用匿名函數(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)建了一個簡單的函數(shù),它接受一個可調(diào)用的函數(shù)并將其應用于其他參數(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

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

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!");
}

“這種方法避免了拋出一個異常。回想一下拋異常的情況,它會導致程序堆棧展開和記錄寫入,但也不尊重代碼的局部性原則。尤其是它不服從空間地域性,它指出應該依次執(zhí)行的相關陳述應該相互靠近。這在 CPU 架構上有更多的應用,但也可以應用于代碼設計。”這種翻譯型的語句我還是日后在理解吧,說不定有一天就豁然開朗了,畢竟這是一條很遙遠的路。

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

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

使用包裝來控制對特定變量的訪問并提供額外的行為。先看下例子中的這個 class ,下面的例子擴展性較強

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[  ]
關閉

在 PHP 5.4+之后,PHP中的所有函數(shù)都是從 Closure 類創(chuàng)建的對象。使用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
說明

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

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

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

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/26215.html

相關文章

  • 初步認識函數(shù)

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

    Rango 評論0 收藏0
  • [零基礎學python]關于類初步認識

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

    王巖威 評論0 收藏0
  • 從零帶你入門Socket編程

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

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

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

    Anchorer 評論0 收藏0

發(fā)表評論

0條評論

wwq0327

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<