Как стать автором
Обновить
4
0

Пользователь

Отправить сообщение
Вы ничем не рискуете: я застал переход с пхп 4 на пхп 5, до появления такого синтаксиса оставалось меньше 10 лет…

Да, квадратные скобки как замена array() появились в PHP 5.4, но вовсе не в этом суть.
Ну хорошо, вот, это будет работать хоть на PHP 4:


$months = array(1 => 'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь');
Только надо учитывать, что это ассоциативный хэш, а не массив, и поэтому доступ по индексу выполняется в несколько раз медленнее.

Чем где? В PHP любой массив всегда ассоциативный, что ты с ним ни делай.
Впрочем, они их хорошо оптимизировали, потому производительность – далеко не главная проблема такого архитектурного решения.

because you didn’t want to expose your dad as a fraud
потому что вам не хочется выставлять вашего папу жуликом

"Жулик" тут совсем не к месту. Может, "самозванец" или перефразировать с "некомпетентный"…

Рискуя быть занудой:


$months = [1 => 'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];
Вопрос, какой совместимости.

Очевидно, нужно перейти на Chromium, чтобы растерять вообще всех пользователей, как это сделала Opera. Так победим.

только уже в 9999 году

Если читающее сейчас мой комментарий создание в 10 000-м году или позже и использует MariaDB или MySQL, то… да что с вами не так %)?

Иллюстрация идентичности:


> SELECT unix_timestamp(TIMESTAMP '2020-04-04 13:42:42') AS ts;
1586007762
> SELECT timestampdiff(SECOND, DATE '1970-01-01', TIMESTAMP '2020-04-04 13:42:42') AS ts;
1586007762

> SELECT from_unixtime(1586007762) AS dt;
2020-04-04 13:42:42
> SELECT DATE '1970-01-01' + INTERVAL '1586007762' SECOND AS dt;
2020-04-04 13:42:42.000000
> SELECT CAST(DATE '1970-01-01' + INTERVAL '1586007762' SECOND AS DATETIME) AS dt;
2020-04-04 13:42:42

> SELECT unix_timestamp(TIMESTAMP '2020-04-04 13:42:42.123090') AS ts;
1586007762.123090
> SELECT datediff(TIMESTAMP '2020-04-04 13:42:42.123090', DATE '1970-01-01') * 86400 + time_to_sec(TIMESTAMP '2020-04-04 13:42:42.123090') AS ts;
1586007762.123090

> SELECT from_unixtime(1586007762.123090) AS dt;
2020-04-04 13:42:42.123090
> SELECT DATE '1970-01-01' + INTERVAL '1586007762.123090' SECOND_MICROSECOND AS dt;
2020-04-04 13:42:42.123090
И говоря, что конструкцию вида «for i in range(len(seq)):» не стоит использовать, нужно уточнять, что это касается исключительно ситуаций итерирования обьекта. Для имитации же именно поведения for эта конструкция вполне легальна.

Я не спорю, и статья явно направлена на тех, кто совсем не в курсе и допускает довольно серьёзные неточности.


с названием одного, а механикой другого.

Моя же позиция в том, что название for часто используется и для другой механики во многих языках.
Например, в Rust, Kotlin, Julia, Nim, Zig.

Строго говоря в питоне вообще нет «for» — есть только «foreach». И инкремента индекса (как и самого индекса) тоже нет — есть проход по списку, сгенерированому функцией range() или поданому явно.

Что я и сказал, да.


Строго говоря в питоне вообще нет «for» — есть только «foreach».

Касательно терминологии, есть множество языков, где for выступает именно как оператор обхода по итератору (условно).
Самый яркий пример – Raku, потому что там есть for @scores.kv -> $i, $score { и есть loop (my $i = 0; $i < @scores.elems; ++$i) {.


С++ обычно не рассматривается в отрыве от С, так как является его надмножеством, а в С вполне есть старый добрый «for» без всяких последовательностей.

Почему же не рассматривается? Рассматривается.
Особенно когда обсуждаются специфичные для C++ особенности.


Вот где действительно объединены, так это в C++, <…>

Я имею в виду, что оператор for используется для обоих вариантов цикла в C++. В C, естественно – нет.

и то что в питоне их обьединили в одно не ставит между ними знак равенства

Это не совсем так, for в Python только один, и для инкремента числа используется тот же самый обход последовательности, генерируемой функцией range.
Вот где действительно объединены, так это в C++, Java, JavaScript и (частично) в Perl5.

Есть такой длинный и уродливый:


for x, y, value in [(x, y, v) for (x, l) in enumerate(array) for (y, v) in enumerate(l)]:

Лучше уж в две строки.

for i, list in enumerate(scores, 1):
    for j, score in enumerate(list, 1):
        print(i, j, score)
имея опыт работы с другим популярным языком программирования, вроде PHP или JavaScript, то вам знакома методика применения переменной-счётчика, хранящей, например, индекс текущего элемента массива, обрабатываемого в цикле.

В PHP самым стандартным является такой подход:


$scores = [54, 67, 48, 99, 27];
foreach ($scores as $k => $score) {
    echo "{$k} {$score}\n";
}

Банальнейшая вещь и с незапамятных времён.
Но это, конечно же, не совсем enumerate, ведь вместо инкремента тут ключи ассоциативного массива (в данном случае не отличающиеся).


А вот сие уже гарантированно эквивалентно:


$scores = [54, 67, 48, 99, 27];
foreach (array_values($scores) as $i => $score) {
    echo ($i + 1) . " {$score}\n";
}

Сам enumerate тоже можно переизобрести, если очень хочется:


function enumerate(array $array, int $start = 0): array
{
    $keys = range($start, count($array) - 1 + $start);
    return array_combine($keys, $array);
}

$scores = [54, 67, 48, 99, 27];
foreach (enumerate($scores, 1) as $i => $score) {
    echo "{$i} {$score}\n";
}

Либо с yield (медленнее при использовании с массивами (PHP 7.4)):


function enumerate(iterable $iterable, int $start = 0): iterable
{
    $i = $start;
    foreach ($iterable as $v) {
        yield $i++ => $v;
    }
}

Ещё при необходимости дробной части можно получить количество секунд так:


SELECT datediff(TIMESTAMP '2038-01-20 00:00:00.123090', DATE '1970-01-01') * 86400 + time_to_sec(TIMESTAMP '2038-01-20 00:00:00.123090');

Так дробная часть сохраняет количество знаков.
К сожалению, всё равно нужно указывать datetime дважды.

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


SELECT timestampdiff(SECOND, DATE '1970-01-01', DATE '2038-01-20');
SELECT DATE '1970-01-01' + INTERVAL '2147558400' SECOND;

Если нужна дробная часть, то уже всё далеко не так приятно, но ничего невозможного:


SELECT timestampdiff(SECOND, DATE '1970-01-01', TIMESTAMP '2038-01-20 00:00:00.123090') + microsecond(TIMESTAMP '2038-01-20 00:00:00.123090') / 1000000;
SELECT DATE '1970-01-01' + INTERVAL '2147558400.123090' SECOND_MICROSECOND;
И если их цель преобразовать строки в числа

Как бы, ord
Неужели так сложно поверить, что числа сравнивать дешевле, чем целые строки, хоть и единичные %)?


это немного высокая цена

Два for на 40 000 циклов суммарно.


ради того чтобы позже выиграть на сравнении чисел вместо строк

А вот сравнение происходит 400 000 000 раз.

минус два цикла с вычислением ord()

Вне цикла подобные манипуляции вообще ничего не значат на общем фоне. Так-то их можно вообще вынести наружу… только зачем?


плюс строгое равенство при сравнении одиночных символов

При сравнении строк иначе и нельзя. А вот при сравнении (гарантированных) чисел никакой разницы тут не будет.


Не говоря уже про UTF-8

Все версии сделаны именно так, чтобы сравнивались именно индивидуальные байты для однородности и простоты (ну, в большинстве случаев).
Но вообще, как ни иронично, именно вариант с конвертацией в массив чисел более юникододружелюбный, потому что с ним для UTF-8 нужно просто заменить ord на mb_ord, а иначе нужно использовать mb_substr; а это, сам понимаешь, уже целый вызов функции внутри цикла.

Сравнение чисел просто немножко дешевле.

Но таблице указано Mono 6.6.0

А, и правда.

Чем мы хуже гошников, в конце-то концов? :)

Таки тем, что это C#7 без особой на то причины (а там замер с Mono 5).

1

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность