Видеоблогер Конор Хекстра использовал разные языки программирования, чтобы решить одну и ту же задачу. Попутно выяснилось, что у Фортрана полно поклонников.

На YouTube-канале code_report, «посвященном соревновательному программированию», есть интересная работа Конора Хекстры, старшего инженера NVIDIA, работающего над пакетом RAPIDS для конвейеров обработки данных и аналитики. Хекстра увлекается просмотром решений с конкурсов по программированию (LeetCode, HackerRank, Topcoder и Codeforces), а также создаёт видеоролики на близкие к программированию темы, такие как структуры данных и алгоритмы.

У Фортрана оказалось много поклонников

Чтобы исследовать подходы к решению одной задачи на 16 разных языках программирования, Хекстра выбрал относительно простое задание с конкурса программирования LeetCode: определите наименьшее и наибольшее число из заданного списка, а затем найдите их наибольший общий делитель.

Языки, выбранные для решения:

  • C++

  • Rust

  • D

  • Clojure

  • Ruby

  • Elixir

  • Raku [Perl 6]

  • Haskell

  • Racket

  • Julia

  • Python

  • APL

  • J

  • BQN

  • Pharo Smalltalk

  • Fortran

(В видео поясняется, что последние два языка были добавлены по просьбам зрителей. «Я сделал опрос в Твиттере, и Fortran получил целых 27 лайков!», — объясняет Хекстра. Так что пришлось его тоже включить).

Кардинальные различия

Хотя исходная задача была простой, подходы к её решению в разных языках сильно отличаются. Особенно при переходе на язык массивов. Там подход будет принципиально отличаться от того же Python или Ruby.

Так, в Python уже есть встроенные функции для всех необходимых операций: для нахождения наименьшего числа, наибольшего числа, даже для «наибольшего общего делителя».

Но всё стало выглядеть абсолютно по-другому, когда Хекстра добрался до функционального языка Haskell. Его функция liftM2 отображает значения минимума и максимума для входных данных функции gcd — и все это в одной строке.

И самое главное, поскольку Haskell использовал стиль программирования “Tacit” или point-free (стиль программирования без промежуточных переменных, предполагает использование конвейерных функций и комбинаторов), который не указывает аргументы в определениях функций, решение Haskell даже не нуждалось в упоминании массива чисел.

Низкоуровневый язык программирования D требует, чтобы функции были импортированы. Но он хотя бы использует универсальный синтаксис для вызова функций знакомым методом из объектно-ориентированного программирования. Хекстра посчитал это довольно милым.

Хекстра жаловался, что в Rust и в C++ слишком много «формальностей». Обе функции, и min, и max, требуют использования iter() для прохождения итераций по каждому значению в списке чисел, и unwrap() для извлечения значения из более сложного модуля Result, который включает информацию об обработке ошибок.

И, как заметил Хекстра: «чтобы получить доступ к функции gcd приходится преодолеть кучу лишнего в пространстве имён num::integer:: . Но в остальном это очень хорошее решение».

Так как Хекстра является поклонником языков программирования массивов, в его исследовании нашлись и более существенные различия. Решение в APL (справа от розовой стрелки) состоит всего из пяти символов. (Первые два символа находят максимальное значение, последние два символа находят минимальное значение, а зеленая буква v в середине находит их наибольший общий делитель.)

Похожая структура есть и в языке программирования J (ещё один язык программирования массивов, но J является усовершенствованной версией APL, в которой используются диаграммы ASCII, а не символы Unicode»). Функция нахождения максимума представлена здесь ​​​​символом “>”, а функция поиска минимума — “<”.

Чем дальше, тем всё более экзотическими становились решения. BQN из семейства  APL (согласно APL Wiki) всё ещё является языком, управляемым массивами, но он использует свой уникальный набор символов. Поскольку в нём нет встроенной функции для нахождения наибольшего общего делителя, эта функция должна быть определена в отдельной строке кода.

Хекстра признался, что просто скопировал код из онлайн-источника. Как только функция стала определена в первой строке, появилась возможность вызвать её, как часть решения, во второй строке.

Соревнование со зрителями

Судя по реакции аудитории, им понравились соревнования языков, и они охотно делились собственным опытом. 

“Некоторые интересовались решением для Cobol, так что я решил попроб��вать свои силы: https://t.co/Pi7OSCdeIl Всего-то 91 строка…

На данный момент видео получило сотни комментариев, в которых предлагались лучшие варианты решений. 

Решение на языке Julia был похоже на решение для Python, только с оператором «splat» (в данном случае троеточие), означающим, что будет проверено более одного значения:

Но зрители предложили более простой синтаксис. В Julia есть две встроенные функции поиска минимума и максимума, которые не требуют многоточия. Также есть одна функция, которая возвращает оба значения “extrema”. А затем решение стало еще проще, когда Хекстра взял оператор склеивания функций для создания point-free решения (с функцией сбора, преобразующей два значения в формат списка, который можно передать в gcd).

«На мой взгляд, это самое красивое решение из всех, — добавил Хекстра — отчасти потому, что оно демонстрирует элегантность point-free решений.»

Затем зрители предложили ещё несколько изящных улучшений для решения Хекстры на Raku (язык, ранее известный как Perl 6). В Raku gcd — это «инфиксная» функция, которую можно поместить между двумя значениями  аналогично математическим операторам (например, плюс или минус). И тогда два значения, между которых его поместили, могу�� быть результатами методов объектного стиля, вызываемых массивом чисел. 

По иронии судьбы, решение Pharo Smalltalk оказалось похожим на решение Raku (со своей собственной функцией gcd:, которая появлялась как «инфиксный» оператор между двумя функциями, возвращающими минимум и максимум).

Но зрители отметили, что у Raku также есть специальная функция minmax, которая возвращает оба значения одновременно, что приводит к ещё одному однострочному решению, где этот результат становится входными данными для функции gcd.

Хекстра счёл такое решение предпочтительным.

По фану с Фортраном

В первом видео Хекстра посчитал решение, написанное на Fortran, худшим, потому что оно тоже было заполнено кучей формальностей и усложнений. Но он уточнил, что «это первый кусок кода на Фортране, который я написал в своей жизни, так что, скорее всего, есть лучшие решения… После 40 минут отладки и запуска этого кода я решил, что пора закругляться».

Но в последующем видео Хекстра признался, что получил потрясающий ответ от сообщества Fortran. Джейкоб Уильямс, программист Фортрана и орбитальный механик в Космическом центре НАСА имени Джонсона, ответил, что ему для решения задачи потребовалось около 5 минут (с gcd из кода rosetta). 

Также видео Хекстры вызвало отклик у Милана Курчича, давнего программиста на Фортране и автора книги «Современный Фортран». Курик поблагодарил Хекстру за включение Фортрана в свой обзор и предложил альтернативное решение, которое включает функцию наибольшего общего знаменателя:

Оказалось, что временная переменная res не нужна, так как результат можно просто вернуть, не присваивая ему отдельного значения. И некоторые обновления синтаксиса в Фортране теперь позволяют указывать длину списка с помощью одного лишь двоеточия вместо громоздкой переменной numsSize. Это позволяет избавиться от целой строки кода. Итого вместо огромного кода можно прийти к всего двум строкам в теле функции!

Официальный канал Fortran в Твиттере даже ретвитнул первоначальный твит Хекстры с видео, с комментарием, что они собираются работать над улучшением своих учебных пособий в будущем. По мнению инженера, именно так должно работать сообщество, если оно хочет привлечь новых людей к своему языку.


Что ещё интересного есть в блоге Cloud4Y

→ Как открыть сейф с помощью ручки

→ OpenCat — создай своего робокотика

→ Как распечатать цветной механический телевизор на 3D-принтере

→ WD-40: средство, которое может почти всё

→ Изобретатели, о которых забыли

Подписывайтесь на наш Telegram-канал, чтобы не пропустить очередную статью. Пишем только по делу. А ещё напоминаем про второй сезон нашего сериала ITить-колотить. Его можно посмотреть на YouTube и ВКонтакте.