На прошлой неделе я писал о некоторых крайних случаях правдоподобия в JavaScript. На этот раз у меня есть небольшая заметка об элегантной обработке нулевых/неопределенных значений.

null — названный его изобретателем C.A.R. «ошибкой на миллиард долларов». Хоар — большинство программистов, вероятно, хорошо знакомы с этим (и почему это может быть классифицировано как ошибка!)

Наверняка мы все писали примерно такой код:

if(foo != null) {
  // Do something with foo
}

Но что, если foo — это объект с несколькими уровнями вложенных объектов? Вы, вероятно, согласитесь, что писать что-то вроде этого становится немного громоздко:

if(foo != null) {
  if(foo.bar != null) {
    if(foo.bar.baz != null) {
      // Now it's safe to use foo.bar.baz
    }
  }
}

В некоторых более современных языках (Kotlin, JavaScript 2020, Swift и т. д.) есть поддержка так называемых «безопасных вызовов/необязательных цепочек», и выглядит это так:

x = foo?.bar?.baz?.doSomething()

? указывает, что правая часть должна оцениваться только в том случае, если левая часть не равна null. Однако если какая-либо часть этого выражения равна null, то x будет null.

Что, если бы мы захотели указать, какое значение должно иметь x в случае, если какая-либо из null проверок не пройдена? Очевидно, мы могли бы добиться этого, проверив, является ли x null после оператора, а затем присвоив ему другое значение, но если бы мы хотели, чтобы x было константой, это было бы невозможно.

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

x = foo?.bar?.baz ? foo?.bar?.baz?.doSomething() : <fallback value>

На мой взгляд, это повторяется, а также подвержено ошибкам — если doSomething() возвращает null, то x все еще может быть null! Вы можете обойти это, поставив ?.doSomething() перед ? тернарного оператора, но уверены ли мы, что безопасно вызывать doSomething() более одного раза? Это может иметь побочные эффекты, которые вносят тонкие ошибки в наш код или требуют больших ресурсов и снижают производительность нашего приложения.

Вместо этого я хотел бы предложить лучший способ — нулевой оператор объединения:

x = foo?.bar?.baz?.doSomething() ?? <fallback value>

Таким образом, x все еще может быть константой, мы будем перехватывать любые возможные значения null во всей цепочке и вызывать doSomething() только один раз (максимум).

Теперь, если вы уловили это, почему я назвал это оператором объединения null(ish)? Это связано с тем, что в JavaScript необязательный оператор цепочки и оператор объединения null применяются ОБА к null и undefined. Аккуратно, да?

Я знал об этой концепции, работая в Kotlin, где этот функционал называется «оператор Элвиса». Он пишется как ?: — что немного похоже на макушку головы Элвиса (глаза и его фирменная вьющаяся прическа) — плюс, в сообществе Kotlin мы можем помнить, что все, что происходит справа от оператора, происходит, когда « Элвис покинул здание» (т.е. если вы столкнулись с null и оставили необязательную цепочку) И да, я знаю — иногда программисты могут быть настоящими кретинами. ;-)

Теперь, когда я работал в React Native с использованием TypeScript (который построен на основе JavaScript), я обнаружил, что эта функциональность также существует. Это привело меня к открытию того же понятия в Swift — «нулевого оператора объединения» (представленного ??).

Все это к тому, что я думаю, что это действительно здорово, что все больше и больше современных языков программирования сходятся и поддерживают все больше похожих способов написания кода. У каждого языка всегда будут свои особенности (а также преимущества и недостатки), но я думаю, что мы становимся намного ближе к миру, в котором разработчики Android могут читать кодовую базу iOS и понимать, что происходит (не так было тогда, когда они еще были написаны). в Objective C), или традиционный веб-разработчик может работать над мобильным приложением (уже реальность благодаря таким технологиям, как React Native).

Знаете другие языки, которые поддерживают какой-либо вариант необязательного связывания/слияния нулей? Я хотел бы услышать от вас в комментариях!

Хотите работать со мной в замечательной команде цифровых продуктов Accenture? Мы нанимаем мобильных разработчиков, веб-разработчиков и больше!