«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Ирония статической типизации в динамических языках

Ирония статической типизации в динамических языках

Опубликовано 7 ноября 2024 г.
Просматривать:511

Вы также можете прочитать эту статью на Medium.

Всегда забавно видеть, как языки программирования развиваются с течением времени.

Однажды, когда я начал свой путь в мире разработки программного обеспечения, динамические языки, такие как Python, PHP и JavaScript, ценились за их гибкость и лаконичный синтаксис, подходящий для быстрой разработки.

Однако по мере развития этих слабо типизированных языков они включают в себя особенности строго типизированных языков, что делает их очень похожими на C и Java:

  • Python: возможности подсказки типов, представленные начиная с версии 3.5 в 2015 году и улучшенные в версии 3.12 в 2022 году.
  • PHP: объявленные типы появились в версии 7 в 2015 году.
  • JavaScript: расширен выпуском TypeScript в 2012 году, определенным как «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 г.) продвинулся дальше, добавив поддержку значений null, true и false как отдельных типов:

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

Где ирония?

Не воспринимайте эту статью как возражение против этих новых функций, я признаю преимущества использования строго типизированных языков. Однако, например, использование аннотаций типов в Python не мешает вам изменять типы ваших переменных:

x: int = 0
x = "John" 
print(type(x))   # 

То же самое и для PHP, на консоли выводится только предупреждение об устаревании.

Можно спросить, почему тогда интерпретатор позволяет нам выполнить этот код?
Это потому, что эти языки устроены таким образом: они динамически типизированы по определению. Если мы удалим эту характеристику, они больше не будут динамическими; они станут строго типизированными языками, такими как C, но медленнее.

Надеюсь, вы можете попросить своего интерпретатора быть более жестким, установив для strict_types значение true в вашем PHP-файле:

declare(strict_types=1);

На Python вы можете использовать пакет mypy для анализа кода и выявления ошибок:

$ mypy program.py
error: Incompatible types in assignment (expression has type "str", variable has type "int")  [assignment]

Вы можете рассматривать mypy как советник, сообщающий вам, что вы сделали неправильно, но это не мешает вам выполнять свой код на свой страх и риск.

The Irony of Static Typing in Dynamic Languages

Даже если вы не уверены в типе вашей переменной, вы все равно можете использовать оператор объединения, чтобы сократить список допустимых типов:

Следующие примеры из PHP и Python показывают, как это сделать:

y: int | float = f(x)   # introduced in Python 3.10
int | float $y = f($x)  // introduced in PHP 8.0
let y: number | string  // typescript

Жертвуем ли мы читабельностью кода?

Десять лет назад я решил использовать Python для своей докторской диссертации из-за его простоты и возможности быстро создавать прототипы новых идей. Затем я начал использовать его и в других своих проектах.

Теперь я читаю некоторые странные PEP и задаюсь вопросом, действительно ли стоит усложнять мою кодовую базу, включая эти новые функции.

Давайте рассмотрим пример функции, которая печатает элементы словаря. Вот первоначальная версия:

def print_attributes(**kwargs):
    for key, value in kwargs.items():
        print(key, value)

person = {"name": "John", "height": 1.84}
print_attributes(**person)

При использовании рекомендаций PEP 692, представленных в Python 3.12, код становится следующим:

from typing import TypedDict, Unpack

class Person(TypedDict):   # create a class inheriting from TypedDict
    name: str                  
    height: float           

def print_attributes(**kwargs: Unpack[Person]) -> None:  # use the Unpack operator
    for key, value in kwargs.items():
        print(key, value)

person: Person = {"name": "John", "height": 1.84}  # create an instance of the class
print_attributes(**person)

Вкратце: мы создали класс, который наследует от TypedDict, указали имя и тип каждого элемента и использовали оператор Unpack, чтобы сообщить «mypy», что полученный объект является TypedDict.

В результате размер нашего кода увеличился вдвое. Если бы у нашего объекта было больше элементов, оно стало бы еще длиннее.

К счастью, мы можем использовать статическую типизацию для некоторых частей нашего кода, а остальную часть оставить динамической. Или мы можем вообще не использовать его, если захотим.

The Irony of Static Typing in Dynamic Languages

Когда нам следует его использовать?

Не чувствуйте необходимости переписывать всю свою кодовую базу только потому, что вы узнали новую замечательную функцию.

Эти новые функции подобны инструментам. Мой совет — используйте их с умом:

Используйте статическую типизацию в следующих сценариях:

  • При получении данных из внешних источников, таких как базы данных, библиотеки и API.
  • В критических частях вашего кода, где сбой недопустим.
  • Когда в вашей кодовой базе часто встречаются ошибки.

Избегайте использования статической типизации, если вы:

  • Разработка прототипа для быстрой проверки вашей идеи.
  • Реализация внутренней логики, при которой проверка типов приведет только к созданию многословного кода без каких-либо преимуществ.
  • Просто отображение данных на экране (например, построение диаграмм, изображений, чисел…).
  • Написание сценария командной строки без участия пользователя.

Имейте в виду, что когда дело доходит до кодирования, золотым правилом всегда является стремиться к простоте, за исключением случаев, когда у вас есть веская причина усложнять вещи.

Заявление о выпуске Эта статья воспроизводится по адресу: https://dev.to/aminehorseman/the-irony-of-static-typing-in-dynamic-languages-31g1?1.
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3