首頁  >  文章  >  後端開發  >  動態語言中靜態型別的諷刺

動態語言中靜態型別的諷刺

DDD
DDD原創
2024-11-03 06:28:30511瀏覽

您也可以在 Medium 上閱讀這篇文章。

當我們看到程式語言如何隨著時間的推移而演變時,總是很有趣。

曾幾何時,當我開始進入軟體開發世界時,Python、PHP 和 JavaScript 等動態語言因其靈活性和適合快速開發的簡潔語法而受到讚賞。

然而,隨著這些弱型別語言的發展,它們融合了強型別語言的特性,使它們與 C 和 Java 非常相似:

  • Python:自 2015 年版本 3.5 開始引入類型提示功能,並在 2022 年版本 3.12 中增強。
  • PHP:2015 年版本 7 中引入的聲明類型。
  • JavaScript:透過 2012 年 TypeScript 的發布進行了擴展,定義為「具有類型語法的 JavaScript」。

為什麼會有這樣的轉變?

在嚴格型別語言中,我們在程式碼中明確定義變數的型別。目標是在執行程式之前捕獲開發階段的錯誤,並向編譯器提供有關分配給這些變數的記憶體大小的提示。

// C++ example: 'y' will be an integer
float x = 3.14;
int y = x;  //  y = 3 (ignored the decimal part of the number)

另一方面,動態類型語言(例如 Python、PHP 和 JavaScript)允許我們建立變數並讓解釋器在執行時間暗示它們的類型:

# In python and PHP: 'y' will take the same type as 'x'
x = 3.14
y = x  // y = 3.14 (float)

動態語言中如何引入顯式類型?

在下面的範例中,我們使用動態和靜態類型來聲明相同的函數。

Python:

# using the classic syntax:
def add(x, y):
    return x + y
# using explicit typing:
def add(x: int, y:int) -> int:
    return x + y

JavaScript / TypeScript:

// using the classic syntax
function add(x, y) {
    return x + y;
}
// using explicit typing
function add(x: number, y: number): number {
    return x + y;
}

PHP:

// using the classic syntax:
function add($x, $y) {
    return $x + $y;
}
// using explicit typing:
function add(int $x, int $y): int {
    return $x + $y;
}

PHP 8.2(於 2022 年 12 月發布)透過引入對 null、true 和 false 作為獨立類型的支援來進一步推動它:

public null $nil = null;
public false $false = false;`

諷刺在哪裡?

不要將這篇文章視為對這些新功能的反對,我確實承認使用嚴格類型語言的優勢。然而,例如,在 Python 中使用類型註解並不能阻止您更改變數的類型:

x: int = 0
x = "John" 
print(type(x))   # <class 'str'>

PHP 也是一樣,它只會在控制台上列印 Deprecated 警告。

有人可能會問為什麼解釋器允許我們執行這段程式碼?
這是因為這些語言是這樣建構的:它們根據定義是動態類型的。 如果我們刪除這個特性,它們將不再是動態的;它們將成為像 C 一樣的嚴格類型語言,但速度較慢。

希望您可以透過在 PHP 檔案中將 strict_types 設為 true 來要求解釋器更加嚴格:

declare(strict_types=1);

在 python 中,您可以使用「mypy」套件來分析程式碼並捕獲錯誤:

// C++ example: 'y' will be an integer
float x = 3.14;
int y = x;  //  y = 3 (ignored the decimal part of the number)

您可以看到「mypy」作為顧問,告訴您做錯了什麼,但這並不能阻止您執行程式碼,風險由您承擔。

The Irony of Static Typing in Dynamic Languages

即使您不確定變數的類型,您仍然可以使用聯合運算子來減少接受類型的清單:

以下來自 PHP 和 Python 的範例展示瞭如何做到這一點:

# In python and PHP: 'y' will take the same type as 'x'
x = 3.14
y = x  // y = 3.14 (float)

我們是否犧牲了程式碼的可讀性?

十年前,我決定使用 Python 攻讀博士學位,因為它簡單且能夠快速建立新想法原型。然後我也開始將它用於我的其他項目。

現在,我發現自己閱讀了一些奇怪的 PEP,並質疑自己是否真的值得透過包含這些新功能來使我的程式碼庫複雜化。

讓我們來看一個列印字典項目的範例函數。這是初始版本:

# using the classic syntax:
def add(x, y):
    return x + y
# using explicit typing:
def add(x: int, y:int) -> int:
    return x + y

透過使用 Python 3.12 中引入的 PEP 692 的建議,程式碼變成:

// using the classic syntax
function add(x, y) {
    return x + y;
}
// using explicit typing
function add(x: number, y: number): number {
    return x + y;
}

總結:我們建立了一個繼承自 TypedDict 的類,指定了每個項目的名稱和類型,並使用 Unpack 運算子告訴「mypy」接收到的物件是一個 TypedDict。

結果,我們的程式碼大小增加了一倍。如果我們的物件有更多的項目,它會變得更長。

幸運的是,我們可以對程式碼的某些部分使用靜態類型,而將其餘部分保留為動態類型。或者,如果我們願意,我們可以選擇根本不使用它。

The Irony of Static Typing in Dynamic Languages

我們什麼時候應該使用它?

不要因為學到了一個新的、閃亮的功能而感到有重寫整個程式碼庫的壓力。

這些新功能就像工具。我的建議是明智地使用它們:

在下列場景中使用靜態型別:

  • 從外部來源(例如資料庫、庫和 API)檢索資料時。
  • 程式碼中不允許失敗的關鍵部分。
  • 當您的程式碼庫容易出現頻繁錯誤時。

在下列情況下避免使用靜態型別:

  • 設計原型以快速測試您的想法。
  • 實作內部邏輯,其中類型檢查只會導致冗長的程式碼,沒有任何好處。
  • 僅在螢幕上顯示資料(例如繪製圖表、圖像、數字...)。
  • 編寫無需使用者輸入的命令列腳本。

請記住,在編碼方面,黃金法則始終是力求簡單,除非您有充分的理由使事情複雜化。

以上是動態語言中靜態型別的諷刺的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn