教你用兩行代碼給PHP7添加一個“非空合併”語法糖

来源:https://www.cnblogs.com/a609251438/archive/2020/05/12/12878233.html
-Advertisement-
Play Games

我們知道從 PHP 5.3 起三元運算符 ? : 有一個寫法簡潔寫法是這樣的: <?php $a = 0; $b = $a ?: 1; # $b 1 這實際上相當於: <?php $a = 0; $b = $a ? $a : 1; # $b 1 在 PHP5 中,語法分析是這樣寫的: | expr ...


我們知道從 PHP 5.3 起三元運算符 ? : 有一個寫法簡潔寫法是這樣的:

 

<?php
$a = 0;
$b = $a ?: 1; # $b === 1

  

這實際上相當於:

<?php
$a = 0;
$b = $a ? $a : 1; # $b === 1

  

在 PHP5 中,語法分析是這樣寫的:

|   expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
 expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
 expr     { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }
|   expr '?' ':' { zend_do_jmp_set(&$1, &$2, &$3 TSRMLS_CC); }
 expr     { zend_do_jmp_set_else(&$$, &$5, &$2, &$3 TSRMLS_CC); }

  

在 PHP7 中,由於 AST(抽象語法樹)的引入,語法分析有些簡化:

|   expr '?' expr ':' expr
 { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, $3, $5); }
|   expr '?' ':' expr
 { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, NULL, $4); }

  

PHP7 中語法分析之後都是寫到 AST 的節點上。從上面可以看出,簡化的 ?: 和完整的三元表達式的區別就是節點中間的值為 NULL。

PHP7 添加了一個合併操作符(T_COALESCE),用於簡化 isset 的條件判斷:

<?php
$b = $a ?? 1;

  

它相當於:

<?php
$b = isset($a) ? $a : 1;

  

僅僅是 isset 判斷,在 為等值時還是會返回b 的值還是為 0 。

這個操作符的語法分析語句是:

|   expr T_COALESCE expr
 { $$ = zend_ast_create(ZEND_AST_COALESCE, $1, $3); }

  

如果想將 isset 換成 empty 的效果,也就是說在變數不存在或轉換成 boolean 後為 false 都賦予其他值,需要這樣寫:

<?php
$b = $a ?? 1 ?: 1;

  

顯然上面的表達式中中間一部分稍微有些多餘,那麼做些簡化呢?

現在我想添加一個語法 ??: ,它的作用是對變數做 empty 的判斷。也就是說達到上面 $a ?? 1 ?: 1 的效果:

<?php
$b = $a ??: 1;

  

改起來很簡單,只需要將 ?: 和 ?? 的分析合併一下(註意這裡和上面所有的地方 $1 $2 等符號的數字表示的都是變數或者常量出現的位置順序):

|   expr T_COALESCE ':' expr
 { $$ = zend_ast_create(ZEND_AST_CONDITIONAL,
 zend_ast_create(ZEND_AST_COALESCE, $1, $4), NULL, $4); }

  

僅僅只有兩句,因為並沒有在詞法分析器中添加 Token,所以只能算是個語法糖。

重新編譯一下之後就能看到效果啦。

測試:

$ /usr/local/php/bin/php -r "\$a = 0; echo \$a ?? 1, PHP_EOL;"
0
$ /usr/local/php/bin/php -r "\$a = 0; echo \$a ??: 1, PHP_EOL;"
1 

  

更多學習內容請訪問:

騰訊T3-T4標準精品PHP架構師教程目錄大全,只要你看完保證薪資上升一個臺階(持續更新)

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 關註公眾號“程式員書單” 加個“星標”,每天帶你讀好書! ​ 學習編程,數據結構是你必須要掌握的基礎知識,那麼數據結構到底是什麼呢? 其實數據結構就是用來描述電腦里存儲數據的一種數學模型,因為電腦里要存儲很多亂七八糟的數據,所以也需要不同的數據結構來描述。 瞭解了基本概念之後,接下來我們再來看看 ...
  • 這篇我們介紹一下ES的聚合功能(aggregation)。聚合是把索引數據可視化處理成可讀有用數據的主要工具。聚合由bucket桶和metrics度量兩部分組成。 所謂bucket就是SQL的GROUPBY,如下: GET /cartxns/_search { "size" : 2, "aggs": ...
  • formula 基於 groovy 實現的公式庫 項目地址 "Github" 語法 比如: 支持公式嵌套: 比如: 快速開始 1. 創建 Formula 對象 formula 1. 運行 formula.run("script") 下麵是例子: 預設公式 這裡只是拋磚引玉,實現瞭如下文本公式: UU ...
  • 垃圾回收演算法和垃圾收集器 1.什麼是垃圾回收 對於記憶體當中無用的對象進行回收,如何去判斷一個對象是不是無用的對象。 引用計數法: 每個對象中都會存儲一個引用計數,每增加一個引用就+1,消失一個引用就 1。當引用計數器為0時就會判斷該對象是垃圾,進行回收。 但是這樣會有一個弊端。就是當有兩個對象互相引 ...
  • 前言 那麼今天給大家分享的是關於python爬蟲的一個小案例,爬取的數據是圖片數據,其實咱們互聯網當中包括文本數據、圖片數據、音頻數據、視頻數據。 這些數據只要你在互聯網當中能夠用肉眼看到,都能夠通過我們爬蟲代碼批量的獲取到 cosplay是英文Costume Play的簡寫,日文コスプレ。指利用服 ...
  • 經典排序演算法 創建3個文件:sortArray.h、sortArray.c、sortArrayTest.c。 sortArray.h c include include include "sort.h" // 功能: 列印錯誤信息後就錯誤退出程式. // 參數: expression(錯誤判斷表達式 ...
  • 最開始寫的有很多迴圈的(容易理解,但複雜性高) assume cs:code,ss:stack data segment db '1975','1976','1977','1978','1979','1980','1981','1982','1983' db '1984','1985','1986' ...
  • 1 ## 類 2 ''' 3 在面向對象編程中,你編寫表示現實世界中的事物和情景的類,並基於這些類來創建對象。 4 編寫類時,你定義一大類對象都有的通用行為。基於類創建 對象時,每個對象都自動具備 5 這種通用行為,然後可根據需要賦予每個對象獨特的個性。 6 7 根據類來創建對象被稱為 實例化,這讓 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...