Pull to refresh

20_20 — год, в котором подчеркивание в числовых литералах победило

Reading time3 min
Views10K

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


<?php

print(1_00);
print(100);

Выведет 100100 (проверить онлайн). Этот синтаксический сахар появился в Ada в 1980 году, и он имел переменный успех последние 40 лет. Но за последний год его добавили в javascript, PHP, Go, Scala и даже консервативный Erlang. Я не могу объяснить, что послужило всплеском популярности, поэтому в статье просто опишу историю разделителей в цифрах.


19 68 Algol


На заре программирования не особенно заморачивались с пробелами, а поэтому в Algol в именах переменных и цифрах можно было вставлять пробел. Например, a 1 st var — корректное название переменной, и синоним a1stvar. Код:


BEGIN
    INT  a 1 st var = 1 234 567;
    REAL a 2 nd var  = 3      .    1 4159 26 5 359;
    print((a1stvar, newline, a2ndvar))
END

Выведет (проверить):


   +1234567
+3.14159265359000e  +0

Я не смог найти более ранние версии интерпретатора, но очевидно, так вели себя и предыдущие версии Algol. Также, пишут, что FORTRAN до версии 77 года вел себя аналогично.


UPD: В фортране пробелы в числах и именах можно использовать до сих пор (в режиме fixed-form source files). Но fixed-form source files депрекейтед в стандарте 2018 года.


19_80 Ada


Похоже, что впервые использовать подчеркивание как разделитель в цифрах придумали в 1980 году в Ada. Кроме этого, в Ada можно было указывать числа в системах с любым основанием от 2 до 16. 11 в пятеричной системе (6 в десятеричной) можно было записать 5#11#. Что в свою очередь позволяло делать, такие неочевидные вещи, как I: Float := 3#0.1# — переменная со значением 1/3 (одна треть):


with Ada.Float_Text_IO; use Ada.Float_Text_IO;
procedure hello is
    I: Float := 3#0.1#;
    J: Float := 1_00.0;
begin
    Put(I);
    Put(J);
end hello;

Выведет 3.33333E-01 1.00000E+02 (онлайн).


19_85 Caml


19_87 Perl


Позже, похоже независимо друг от друга, подчеркивание появилось в Caml и Perl. Perl стал первым языком, где (по непонятой мне причине) можно использовать несколько подчеркиваний подряд:


$x = 1_0_0;
$y = 2__5________0;
$z = $x+$y;

print "Sum of $x + $y = $z";

Выведет Sum of 100 + 250 = 350 (проверить).


19_93 Ruby


19_96 OCaml


Это первые два языка, где можно проследить, откуда пришло подчеркивание. OCaml (неожиданно) перенял подчеркивание у Caml, а Ruby создавался под влиянием Perl, откуда и перенял подчеркивание (правда, без возможности ставить несколько подряд).


20_03 D (v0.69)


D стал первым языком, в котором изначально в спецификации подчеркиваний не было, а их добавили позже (через два года после создания).


20_10 Rust


20_11 Java (SE 7)


20_12 Julia


Rust создавался под влиянием OCaml, а Julia под влиянием Ruby. В Java как и в Perl можно ставить несколько подчеркиваний подряд.


20_14 Swift


Под влиянием Rust.


20'14 C++ (v14)


У плюсовиков проблемы всегда отличаются от других. Дело в том, что идентификатор в C++ может состоять из подчеркивания и цифры. То есть, _1 правильное название переменной. И код:


#include <iostream>

int main()
{
  for (int _1 = 0; _1 < 5; ++_1) {
    std::cout << _1 << " ";
  }
}

Выведет 0 1 2 3 4 (проверить). И чтобы не путать название переменных и цифры в C++ разделителем сделали одинарную кавычку 1'00.


UPD: Более опытные объяснили, что подчеркивание конфликтовало с пользовательскими литералами (User-defined literals). Следующий код корректный и выведет 1:


#include <iostream>

constexpr unsigned long long operator"" _0(unsigned long long i)
{
    return 1;
}

int main()
{
    int x = 0_0;
    std::cout << x;

    return 0;
}

20_16 Python (3.6)


20_17 C# (7.0), Kotlin (v1.1)


20_18 Haskell (GHC 8.6.1)


20_19 JS (V8 v7.5, Chrome 75), PHP (v7.4), Go (v1.13), Scala (v2.13)


Тут что-то произошло, и подчеркивание добавили во все основные языки. Здесь бы и хотел сделать замечание, что подчеркивание хоть и не сильно, но усложняет интерпретаторы или компиляторы. Например, из мануала в PHP регулярные выражения для цифровых литералов:


// PHP 7.3
decimal : [1–9][0–9]* | 0
hexadecimal : 0[xX][0–9a–fA–F]+
octal : 0[0–7]+
binary : 0[bB][01]+

// PHP 7.4
decimal : [1–9][0–9]*(_[0–9]+)* | 0
hexadecimal : 0[xX][0–9a–fA–F]+(_[0–9a–fA–F]+)*
octal : 0[0–7]+(_[0–7]+)*
binary : 0[bB][01]+(_[01]+)*

В добавок, теперь в PHP появилось еще больше способов записать одно и тоже число:



20_20 Erlang (v23)


Дольше всех держался Erlang. Но, что удивительно, с самого начала в Erlang можно было, как и в Ada (даже с похожим синтаксисом), записывать числа в произвольной системе исчисления (до 36). Например, следующий код печатает (онлайн) 3z в системе с основанием 36 (=143).


-module(main).
-export([start/0]).

start() ->
  io:fwrite("~w", [36#3z]).

Но подчеркивание в цифрах добавили только спустя 33 года после создания языка.

Tags:
Hubs:
Total votes 50: ↑49 and ↓1+48
Comments36

Articles