Abnormal programming
Programming
Functional Programming
Comments 463
+29

Хорошо, а теперь оцените объем памяти, требуемый для исполнения этой функции.

+3

Время интервью вышло, так что отвечу кратко: возьму uniqueness types, а дальше достаточно умный компилятор всё сделает без дополнительных аллокаций.

+10

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


Компилятор Idris'а, на самом деле, не настолько умён, в него слишком мало ресурсов вкладывается (я удивлюсь, если reverse с uniqueness types он скомпилирует в инплейс), но вот какой-нибудь ghc, когда может подобные вещи вывести (ибо в хаскеле пока нет афинных типов), вполне себе так оптимизирует код.


Чё-то я тут слишком серьёзный, похоже.

+43

Это наверное такой мем от функциональщиков — я раз несколько на Хабре в статьях о ФП видел утверждение, что "компилятор оптимизирует", или что "оптимальный код — забота компилятора". Кажется, иногда это говорили всерьез.

+1
Ну насчет хаскелля не скажу, но, например, в лиспе, lparallels действительно даёт возможность просто писать многопоточный код по сравнению с императивными языками. Да и вообще выявлять, и, главное, оптимизировать узкие места проще (впрочем, не исключаю confirmation bias задач, которые я решал на лиспе)
+3
А кто ещё может оптимизировать? Людям это доверять нельзя, они баги вносят, когда пытаются оптимизировать.
+58
Подчиненный перед лицом начальствующим должен иметь вид лихой и придурковатый, чтобы умом своим не смущать начальства.
+6

Потому что это и не цитата. Просто забавная выдумка, автор которой не известен.

+25

Ну, как минимум, потому, что с телефона это оформлять неудобно. Да и:
"Главная проблема цитат в интернете в том, что люди сразу верят в их подлинность". (с) В. И. Ульянов (Ленин)

0
чтобы умом своим не смущать начальства.
Новый уровень ума — мудрость.
+1
— В чем состоит наипервейшая обязанность придворного? — спросил эмир.
Ходжа Насреддин ответил ему так:
— О великий и блистательный повелитель! Наипервейшая обязанность придворного состоит в каждодневном упражнении спинного хребта, дабы последний приобрел необходимую гибкость, без чего придворный не может достойным образом выразить свою преданность и свое благоговение. Спинной хребет придворного должен обладать способностью изгибаться, а также извиваться во всех направлениях, в отличие от окостеневшего хребта какого-нибудь простолюдина, который даже и поклониться не умеет как следует.

(Повесть о Ходже Насреддине)
+24

Статья вызывает улыбку. Но кроме всего прочего поднимет проблему важности soft skill наряду с развитыми hard skill.

+25

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

+7
Это для вас они скучные.
А у меня знакомый набирал людей на разработку — так кандидаты не знали, сколько бит в байте и сколько байт в 32-разрядном инте. Что такое указатель — вообще страшная тайна, шаманство какое-то…
0
Угу. Там работа с оборудованием на довольно низком уровне — посему кандидатам неплохо было бы знать, как типы данных лежат в памяти.
0
Когда меня брали на, то давали схемы и потом просили описать пути электронов после подачи питания.
И да — это важно знать, если ты пишешь микрокод контроллера шины.
0

А скорость движения электронов спрашивали?
А то бывают интересные версии...

+12
>не знали, сколько бит в байте
Это вы им показали 9-битные и попросили обосновать?
+1
Там действительно мой знакомый, и проект у них вполне практический. И оборудование достаточно стандартное — процессоры x86 почти везде, кое-где вроде как пытались внедрить ARMы. Так что байты там нормальные, восьмибитные.
Но выясняется страшное: приходят собеседоваться специалисты, которые вообще никогда не задумывались о том, как именно данные хранятся в памяти. А им по работе надо пакеты между нодами туда-сюда гонять по чахлым каналам связи…
+2

Неспроста в университетах обучение идёт с основ: базовая логика, структуры данных, ассемблер, С и только потом уже идут C#, Java, Python. Многим это не нравится, потому что не получается сразу начать писать практический код. Но по факту если человек начинает изучение программирования сразу с языка скриптового уровня, то ему потом становится сложно подтягивать базу, потому что это требует времени.

+5

А если с языка низкого уровня, то многие заболевают преждевременной оптимизацией.

0
Возможно, наоборот aka эффект декомпрессии. Не надо байтики руками перекладывать, можно использовать композицию функций, объекты, часть паттернов и гуй из коробки… В итоге код легко пишется, неплохо читается и поддерживается, но жрёт много памяти и проца и местами подтекает.
+1

Нет, чаще народ начинает искать, что быстрее i < n или i <= n — 1, и заменять деление на сдвиги.

0
Такая фигня обычно проходит после первого коммерческого проекта на языке, особенно если сроки горят.
+2

Я видел такое от программистов с годами опыта. В основном они любят утверждать, что софта на ГЦ нет потому что на нем нельзя писать рилтайм приложения, и скоро С++ захватит мир. Невыдуманная история.

0
Насколько я знаю, специфика и подходы к написанию риалтаймовых приложений одинаковы, но дополнительно надо очень хорошо знать устройство виртуальной машины. Имхо, какую-нибудь RTOS я бы на условной Java писать не стал, просто из экономии времени на разработку.
+2

Я к тому, что люди отказываются верить, что за пределами рилтайма и хай-перфоманс плюсов кому-то нужны "тормознутые" жавасишарпоскалы. То есть как раз "преждевременная оптимизация" у людей возведена в абсолют даже после многих лет работы в продакшне.

0
А за это не бьют на ревью или просто тимлды/архитекторы? В кровавом энтерпрайзе опыта работы нет, потому не знаю, что из того, что как бы должно быть, есть на самом деле.
0

Оно не то, что проходит, а даже становится хуже.
Конструкции вида OrderBy(...).First() появляются всё чаще и чаще.

0
т.е. вместо поиска условно максимума сначала сортируют весь массив/лист/etc и получают вместо O(n) O(nlogn)?
0

Суть в том, что если в массиве максимум 10 элементов, такой код проще и понятнее оптимального (придется либо писать свой экстеншн, либо переписывать на ручной цикл), и имеет право а жизнь. Но многие триггерятся на сам факт неоптимальности (Как же так! Тут логарифм появился просто так!). Не знаю, предпочел бы я в данном случае читаемость или цикломатику, но я прекрасно понимаю людей, которые не будут сильно париться над этим. Не потому, что они говнокодеры и им лишь бы пожрать лишних циклов CPU, а потом что там дальше пересылка по сети и выигрышь 10 тактов процессора не даст ничего.

0

Самый читаемый вариант тут всё же- MaxBy(...) или MinBy(...). И этот же вариант как раз даёт нужный профиль исполнения — это ж вообще праздник, согласитесь.

0

Безусловно, но, увы, в стандартной поставке его нет.


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

0

Проблема в том, что многие базовые знания никто не оценивает на собеседованиях, и денег за это особо не платят(точнее выходы в те места где за это платят часто ограниченны ещё кучей требований.

+7

Так я тоже не знаю.


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

+2

Стандарт С ISO 9899:1999 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
определяет что в char можно записать как минимум значения 0..255 или -127..128 (0..UCHAR_MAX, SCHAR_MIN..SCHAR_MAX) 5.2.4.2.1 Sizes of integer types "Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown, with the same sign." и что в char должно быть не менее 8 бит (CHAR_BIT 8), т.е. стандартом допускаются машины с более длинным char.
Байт определен независимо от char как адресуемая единица памяти, без уточнения числа бит: 3.6 byte "addressable unit of data storage large enough to hold any member of the basic character set of the execution environment" "A byte is composed of a contiguous sequence of bits, the number of which is implementation defined"
(POSIX определяет байт как октет, т.е. 8 бит)
Книга комментариев к стандарту http://www.coding-guidelines.com/cbook/cbook1_1.pdf на стр 190 приводит примеры
"Motorola DSP56300 which has a 24 bit word… Analog Devices SHARC has a 32-bit word" и уточняет на 191 стр, что в байте не может быть менее 8 бит "The number of bits must be at least 8, the minimum value of the CHAR_BIT macro" (в стандарте это 6.2.6.1 General сноска 40 "A byte contains CHAR_BIT bits")

+5

Хм, там же последняя фраза в той сноске (в 6.2.6.1/3) говорит


A byte contains CHAR_BIT bits, and the values of type unsigned char range from 0 to 2CHAR_BIT− 1
0
Выходит, что в байте CHAR_BIT бит, а в char — не менее CHAR_BIT бит. Значит, в общем случае неверно, что
Стандарт С определяет байт как размер char
0

5.2.4.2.1/2 намекает на ограничение сверху, так что там, по идее, строгое равенство.

+1
То есть, такая машина невозможна в C:

1. Память — набор 16-битных ячеек, т.е. прибавляя к указателю 1,
void* next = (void*)((size_t)current+1);
получается указатель на следующий 16-битный байт.

2. Регистры есть как 16-битные (int), так и 8-битные (char)
При этом, загрузка ячейки в char урезает содержимое до младших 8 бит, как и при любых конвертациях в целый тип меньшего размера.
int* ptr;
char value = *ptr; // младшие 8 бит
int value = *ptr; // весь 16-битный байт из одной ячейки памяти.
+1

Похоже на то (по крайней мере, 8-битные регистры будут оперировать чем-то отличным от char): минимально адресуемый кусок памяти — 16 бит, значит, CHAR_BIT должен содержать 16 бит, значит, в char должно быть 16 бит (или даже «хотя бы 16 бит», если ослабить формулировку и взять вашу).


Я недостаточно хорошо знаю стандарт С, чтобы судить, разрешает ли он типы меньшие, чем char, в конкретных реализациях. В плюсах-то всё просто: есть bool с очевидно меньшим пространством возможных значений.

0
Ну хорошо, а если в машине есть 24-битные регистры (char) и 32-битные (int), а память остаётся 16-битной. В этом случае я не вижу противоречий со стандартом.
0
the values of type unsigned char range from 0 to 2CHAR_BIT − 1.

Мне сходу не удалось найти причины char и unsigned char совпадать по размеру, но ЕМНИП это так. Так что, получается, charы могут быть только 16-битными.

+1
Правильно.
А ещё посмотрите, как в Си++ и в Си (в stdbool.h) определяется тип bool и как они бинарно совместимы между собой на уровне библиотек (т.е. если взять библиотеку от С и подключить к проекту с Си++). :)
+1
Ох, знали бы вы, сколько багов происходят от того, что два куска программы компилируются с разным определением bool!
0
так кандидаты не знали, сколько бит в байте

Хм… недавно была новость, что кто-то там судился с гуглом, что их на собеседовании завалили, потому что они старые были. Один из аргументов был, что интервьювер посмел допустить, что в байте 8 бит. А ведь "senior" разработчики предположительно с очень старым железом работали. А там от 6 до 40 бит могло быть.


Так что, если ваши кандидаты было достаточно в возрасте, то вы зря на них серчаете.

0
Так что, если ваши кандидаты было достаточно в возрасте, то вы зря на них серчаете.

Мопед не мой, и контора не моя — так что набирал не я. :)
Насколько я знаю, приходили в основном довольно молодые люди — лет 27-35.
И если бы кандидат просто сказал, что по-разному бывает и вот работал он на системе, где в байте 6 бит — никто бы не осерчал, я вас уверяю. Наоборот, это ж прекрасный повод обсудить разные архитектуры. Но у кандидатов просто был ступор — что, мол, за вопросы такие дурацкие, кому в здравом уме может понадобиться знание о размерах типов данных?
0
IMHO это троллинг. Популярная архитектура — 8бит.
Где используется нестандартная — менее 1% от всего?

IMHO это не причина вообще зацикливаться на этом.
+3

Да, поэтому достаточно сказать «стандарт утверждает то-то и то-то, поэтому в общем случае это зависит от целевой архитектуры и настроек компилятора, но в интересующих нас случаях это почти наверняка будет 8 бит».


Если интервьювер ожидал два слова «8 бит!», и такой ответ будет для него минусом, то лучше это выяснить сразу.

0
А вы знаете сколько бит в байте? Я вот оже думал, что знаю. Сказал что 8 — обсмеяли с пруфами.
Теперь прежде чем отвечать про биты и байты, я спрашиваю о том, какая архитектура подразумевается.
+1
Пруфы были предоставлены в железном виде, или в музей водили?
Надо было обсмеять их в ответ и спросить, когда последний раз программировали для невосьмибитной архитектуры для продакшена.
-1
Меня в википедию сводили, так что чувствую себя как девушка, которую на свидание в макдональдс пригласили. (Им это вроде бы не нравится) А так общение было целиком и полностью теоретическим и за кружечкой водки, поэтому почему нет?

До этого момента я шибко не задумывался о размерностях байтов. Думал восьмерку выбрали как наиболее удобную и о существовании невосьмерок не подозревал.
+2
А с порядком байт в многобайтных переменных вас познакомили? :) Не все архитектуры little-endian. Очень прикольно переносить какой-нибудь С/С++ с одной платформы на другую, если используются низкоуровневые фишки (например, чтобы протокол обмена реализовать).
-1
Не, про такое не рассказывали, но я сам где-то и что-то читал. Да и какой в задницу C++ если я тихонько быдлокодерствую на php? Там вообще можно с улицы прийти и сбацать.
+1
А есть ещё дополнительный и прямой код для знаковых чисел. Вояки что-то прямой код любят, как я смотрю. То ли они допкода не знают, то ли это какой-то пережиток 50-х.
Кстати, ip-адреса на big-endian построены в сокетных библиотеках. И функция переворачивания в подарок тоже предусмотрена. :)
+1

Ничего, из C++20 поддержку отличных от two's complement представлений выпилили.

+1
Это хорошо, что она предусмотрена, а то по ощущениям очень скоро никто не сможет написать сокетную библиотеку. XD
+1

Ещё иногда strict aliasing rule по рукам бьёт. Взять для примера труктуры для описания типа сокета:



При этом разработчики компиляторов понимают, что что-то не так в консерватории и, как минимум, GCC разрешает type punning:



Хотя, с т.з. стандарта это тоже UB.

0
Вот как раз это очень даже полезная и актуальная информация, поскольку встречается сплошь и рядом. И не только на Си возникают проблемы.
0

Есть ещё и middle endian. А тот же ARM вообще можно переключать между Big и Little.

+1
Не поверите — сейчас тоже есть всякие DSP с 32 битным char (особенно, отечественные современные копии привета из 80-х). И, что характерно, оно используется. Мы, например, такое используем прямо сейчас.
+1

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

+1

Вот кстати да. Мимоходом всегда интересуюсь, сколько различных целых значений может хранить один байт. И знаете, процентах в 30 люди не знают. Кто-то говорит, что 2^256 или 2^128. Из знающих же многие пишут 2^8 (это хороший знак, в принципе).


Как-то жаловался одному товарищу, что, может, я зря это спрашиваю. Он такой: «Да ты чо, это ж самые самые азы computer science, которые проходят на первых лекциях, их просто обязаны понимать все» — это меня немного успокоило.

+1

Слышал историю, как в Гугле знакомый знакомого проводил заключительное интервью с чуваком, у которого было уже 4 собеса с идеальным фидбеком.


Он дал ему следующее задание для разогрева — есть массив из n даблов, это курс обмена USD <-> EUR по каждому из n дней. В начале есть 1 USD. Нужно ровно один раз поменять его в EUR, а потом в один из последующих дней назад в USD. Сколько может быть максимум в конце?


Он не смог решить это за ЧАС, и чуть не попал на работу, если бы не этот знакомый знакомого.

0
Есть ли решение со сложностью лучше, чем O(n^2)? Может, кандидат его искал больше часа, подумав, что очевидное решение «в лоб» не подходит?
0
В целом я придумал решение за O(n∙logn).
Spoiler header
Нужно использовать двоичную кучу. Перебирая первый искомый индекс (цикл по n), выбирая в оставшейся части массива макс. элемент из кучи, и просеивая кучу, удаляя текущий элемент (log n).
+3

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


Это как ваше решение с кучей, но, если цикл пустить с конца, то максимум можно просто пересчитывать за константу.

0
Первоначальный поиск одного минимального элемента — O(n), но как поддерживать минимум за константу, выкидывая пройденный элемент?

Например, в массиве 1,8,12,4,1 минимум = 1.
Когда мы выкинули первый (или последний) элемент, как за O(1) пересчитать минимум?
+1

Мы пересчитываем минимум в префиксе массива:


Для массива {3, 4, 2, 5, 1} — минимумы будут {3, 3, 2, 2, 1}. Пересчитывается тупо cur_min = min(a[i], cur_min).


А потом для каждого элемента сначала берем предыдущий минимум, а потом текущий элемент.


Вы уже заметили, что для каждого первого дня надо в качестве второго дня брать максимум в суффиксе массива. Аналогично можно для каждого второго дня (обмена назад) брать минимум из всех дней до него. Этот минимум для всех префиксов можно вот так за O(1) пересчитать, потому что тут каждый раз ровно один элемент добавляется в множество, по которому берется минимум.

+1

Конечно. O(N), причём за 1 проход. Это пример очень простой задачи на динамическое программирования. Итерируем по дням и для каждого дня храним 2 числа: MaxUSD и MaxEUR:
MaxEUR[k] — максимальное количество EUR, которое у нас может быть на руках на k-й день.
MaxUSR[k] — максимальное количество USD, которое у нас может быть на руках на k-й день, при условии ровно одного обмена 1 USD -> EUR -> USD.
c[k] — курс обмена


0-й день — база индукции: MaxUSD[0] = 0, MaxEUR[0] = 0.
k-й день: MaxUSD[k] = max(MaxUSD[k — 1], MaxEUR[k — 1] / c[k])
MaxEUR[k] = max(MaxEUR[k — 1], c[k])

0

Вы даже более сложную задачу решили. В условии надо менять ровно один раз туда и ровно один раз обратно. Ваше же решение может менять сколько угодно раз.


И у вас опечатка в последней строчке кода — забыли c[k] на MaxUSD[k-1] умножить.

0
MaxEUR[k] = max(MaxEUR[k — 1], c[k])
Как раз это учитывает ваше предыдущее замечание: если в k-тый день меняем доллары на евро, то все предыдущие обмены игнорируются, начинаем с суммы $1 (я ещё подумал, почему граничное условие MaxUSD[0] = 0, так оно и гарантирует, что был хотя бы один обмен и сработало MaxEUR[k] = c[k]).
0
И у вас опечатка в последней строчке кода — забыли c[k] на MaxUSD[k-1] умножить.

Нет, не забыл. c[k] надо умножать на MaxUSD[k-1], если мы можем сколько угодно раз менять валюту. Но по условию мы можем менять только один раз, а изначально у нас был только 1 USD.

0
Идея интересная, и даже проще для понимания, чем суффиксы.
0
Ммм… Пусть у нас в массиве хранится USD/EUR. Ищем в нём самый правый по позиции максимум. Пусть это будет позиция k. Берём подмассив [0; k-1], ищем там минимум. Делим максимум на минимум, получаем количество USD на выходе. Потом ищем самый левый минимум во всём массиве, затем максимум в [k+1; n]. Считаем ещё одно соотношение максимум/минимум. Сравниваем результаты и берём больший. Где я ошибаюсь?
0
Контр-пример:
3,11,2,3,10,1,3
Лучший вариант: 2-10
Ваш алгоритм находит 2 не лучшие пары: 1,3 и 3,11
0
Да, точно. «У любой задачи есть очевидное простое...» :-)
0
function find(x)
	local min,max,p0,p1,p2=x[1],1,1,1,1
	for i=2,#x do
		local v=x[i]/min
		if v>max then max=v p1=p0 p2=i end
		if x[i]<min then min=x[i] p0=i end
	end
	return max,x[p1],x[p2]
end 
0
Здесь не выполнено требование, что нужен обмен, даже если он невыгоден.
Тестовый пример: 20,10
0
Нет просто обмен в тот же день. 20,20
Но если сильно надо то можно и не выгодный обмен сделать
function find(x)
	local min,max,p0,p1,p2=x[1],0,1,1,1
	for i=2,#x do
		local v=x[i]/min
		if v>max then max=v p1=p0 p2=i end
		if x[i]<min then min=x[i] p0=i end
	end
	return max,x[p1],x[p2]
end
0
Нет просто обмен в тот же день. 20,20
Это запрещено по условиям задачи.
+1
так кандидаты не знали, сколько бит в байте

Ну так это смотря в каком байте. Не любой байт октет.

+5
Скучные задачи, увы, обязательны. И для интервьюера они скучны намного больше, т.к. кандидат видит эту задачу впервые (ну или второй-третий раз), а интервьюер эту задачу видит десятый или сотый раз. Но если такую задачу не дать, а дать сразу интересную (как для Senior'a) и кандидат с ней не справится — то не ясно, то ли задача была слишком сложной (кандидат — джун или миддл), то ли кандидат слабый (даже не джун). А т.к. большинство кандидатов по уровню не выше мидла, то и до интересных задач обычно не доходит дело.
Это из своего личного опыта говорю (как в роли кандидата, так и в роли интервьюера).
0

Тут у интервьюэра софт скилз на нуле. Или :) он умно дождался конца, чтобы формально отфутболить знающего идрис чувака.

+30
Пока читал пост, было ощушение, что вернулся на пятнадцать лет назад и сижу на лекции в университете, где понимаю только знаки препинания.
Вероятно вашему собеседнику вы сломали всю логику собеседования и он пропустил всю часть собеседования и перешёл к шагу «попить кофе после дурацкого собеседования, как же они меня все достали»
Всёж большинство собеседований (по собственному опыту) состоят из обязательной части, где задают очевидные вопросы и ожидают ответы в стиле ЕГЭ и дополнительной, где уже можно обсудить интересные особенности.
+1
Статья однозначно мегазачет, а за ссылку на Aphyr вам отдельное спасибо. Я полнейший балбес, раз умудрился такое пропустить.
+27

А каким образом ваши формальные доказательства покрывают отсутствие багов в Irdis? Т.е. я много раз видел ситуацию, когда программист был 100% уверен в результате (оно не может быть другим) — а оно было, причём по самым дурацким причинам. Например, потому что в динамическом линкере именно данная последовательность бинарных байт вызывала ошибочку и перезаписывала INC на NOOP (бага, бага, закрыта в новой версии, но в продакшене старая непатченная версия). Т.е. логика нам говорит "баги нет", а ядро нам говорит "segmentation fault" для нашего бинаря.


Тесты — они такие...

+9

Более того, формальные доказательства не покрывают правильное понимание решаемой задачи. Если заказчик от меня веб-сайт хотел, а я ему формально верифицированную криптовалюту сделал, то толку-то.


А с юнит-тестов ровно по вашей логике толку примерно столько же. Все скомпилированное приложение целиком надо тестировать.

+3

На самом деле, скомпилированные юнит-тесты уже проверят этот код. Упор на слово "скомпилированные", потому что получится, что unit-test'ы — это такие неявные интеграционные тесты между компилятором, исходным текстом и ОС, где это всё запускается.


… Потому что может быть даже печальнее, например,


idris 1.irdis 
  File "1.irdis", line 1
    revDumb : List a -> List a
            ^
SyntaxError: invalid syntax

(да, alias irdis=python).

+4

Но ведь, опять же, по вашей же логике их вовсе недостаточно. Вдруг в компиляторе/линкере/етц есть баги такие, что юнит-тесты отрабатывают, а всё вместе в составе конечного приложения — нет?

+1
Только юнит тестов никогда не достаточно для полноценной проверки того, что всё работает в сборе. Совсем без юнит тестов тоже может быть тяжело, потому что полноценные интеграционные тесты обычно идут долго, и соответственно не дают фидбека сразу. Получается, что лучше иметь и то и другое (в идеале :))
+1

Ну, если всерьез говорить, то я пишу тесты, чтобы убедиться, что я правильно понял целевую задачу (этакие интеграционные тесты-спеки), и в идеале доказательства на все остальное.

+2
Надеюсь, вы всё-таки не используете Idris в продакшене :). Ну или у компании, в которой вы работаете, будут большие проблемы с поиском замены для Вас, когда вы уволитесь.
+1

Если серьёзно, то компилятор идриса к продакшену ещё не готов, и я при всей моей любви буду против использования его для чего бы то ни было достаточно серьёзного (поэтому сейчас читаю CPDT, ага).

0
Ну так они и в FAQ честно пишут, мол, «Idris is primarily a research tool for exploring the possibilities of software development with dependent types, meaning that the primary goal is not (yet) to make a system which could be used in production.» (С)
+2

Главное — чтобы Эдвин Брэди после переписывания идриса (изначально написанного на хаскеле) на идрисе не начал переписывать идрис снова. А то так никогда до продакшена и не дойдет.

+8
Тестирование программы может весьма эффективно продемонстрировать наличие ошибок, но безнадежно неадекватно для демонстрации их отсутствия.
Edsger Wybe Dijkstra
+1
Это ведь не отменяет необходимости (не совсем правильно подобранное слово) писать тесты, а ваше утверждение
А они не нужны. Мы же формально доказали, что мы обращаем список.
выглядит весьма категорично.
+2

А что добавят тесты в этом случае?


Ну, кроме проверок, что ядро тайпчекера работает корректно, но по этой же логике вам надо писать тесты на фреймворк тестов.

0
А что добавят тесты в этом случае?

+100 к уверенности.
Я не понимаю ваш код, напишите тесты для меня/интервьюера/etc
0

Ну уверенность дело субъективное, у меня от тестов при наличии доказательства не сильно больше не становится.


А непонимание кода… Ну для него не тесты нужны.

+3
В штате компании будут работать программисты разной квалификации, да и вполне вероятно, что вы когда-нибудь уволитесь, а код-то останется.
Как ни крути, с тестами лучше, чем без тестов.
А непонимание кода… Ну для него не тесты нужны.
Но тесты могут поспособствовать понимаю.
0
но по этой же логике вам надо писать тесты на фреймворк тестов.

Вообще-то надо. Тесты — код первого порядка и должен подчиняться всем требованиям релизного кода: стили, ревью, ограничения на выбор зависимостей (и расширений в случае Хаскеля) и наличие тестов.
Другое дело, что писать тесты на внешний код — ну такое.
0

Ну вот так же и код ядра тайпчекера — внешний код.


Тут языкам с тактиками вообще хорошо, которые критерию de Bruijn'а удовлетворяют.

+2

Тесты в данном случае повысит вероятность, что когда кто нибудь поменяет код по какой нибудь причине, изменения в поведении заметят.

0

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

+1

А можно автоматически проверить что доказательство по прежнему относится к этому коду?

+2

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

+1

А если недостаточным для тайпчека, но достаточным для лёгкого изменения логики?

0

Значит, вы доказали не все существенные аспекты вашего алгоритма.


Я бы даже сказал, что в этом всем формальном программировании есть обратная проблема: при не влияющих на семантику изменениях иногда (или даже часто) приходится менять доказательство. По крайней мере, в языках с явным построением proof term'а (вроде идриса).

0

Тесты не только для вас. Если в коде нет опечаток, то код работает именно так, как вы его написали. Довольно много программистов абсолютно уверенны в своем коде. Они же прочитали его 100500 раз и, может быть, в уме или на бумажке уже доказали его. Но иногда такой код все-таки делает не то, что нужно.


Ваше доказательство тут — это тоже код. Вы уверенны что нигде не допустили ошибки? Напишите-ка доказательство для доказательства?


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

0
Ваше доказательство тут — это тоже код. Вы уверенны что нигде не допустили ошибки? Напишите-ка доказательство для доказательства?

А вы просите написать тесты для тестов?

0

Обычно тесты сильно проще той магии, что вы тут используете. Буквально input = ...; output = Call(input); Assert(output = ...).

0

Так доказываемое утверждение тоже достаточно простое. Буквально revDumb xs = revAcc xs — проще любых тестов. Или, если отталкиваться от определения обращения, foldl f init (revDumb xs) = foldr (flip f) init xs. Тоже легко прочитать и понять, что утверждается.

0

А вот само доказательство — с двумя леммами и кучей кода — ну нифига не простое.

0

Я не очень понимаю, как эта проверка работает. Можно ли там в доказательстве написать какой-нибудь бред вида True = False, только завуалированный, и из него вывести правильность любого утверждения?

0

Нет, иначе толку с этих формальных доказательств-то.


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

0
Просим, и пишем.
У меня уже дважды по-крупному случалось, что тестовая среда начинала гнать false positives.
Да, может, в чём-то сами виноваты — переусложнили обстановку. Но не уверен, что более простая схема взлетела бы.
Поэтому приёмы убедиться, что тесты сами что-то проверяют — обязательны.
И это не TDDʼшное «сначала должно упасть» — нет, проверяться на это должно и давно существующее, хотя бы в характерных избранных точках и ситуациях.

Но тут существенно, конечно, что тест должен читаться в разы проще тестируемого кода. Иначе — нет смысла. В исходном постинге это явно не соблюдается…
+1
Как вы только что процитировали, тесты позволяют реально только продемонстрировать наличие ошибок. Но не их отсутствие. Что бы вы хотели ими продемонстрировать? Что код работает правильно? Так они этого не показывают (в общем случае). Что правильно работает один случайно выбранный пример?

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

А если вы не понимаете доказательство, то скорее всего вы не понимаете, что формально означает обратить список (и это в общем типично для многих нетривиальных задач) — то откуда у вас после тестов уверенность-то возьмется +100%, что задача решена верно? Для этого уж как минимум придется прикрутить что-то типа property based testing, а там снова будут доказательства, и все по-новой…

Ну то есть, что для вас субъективно это важно — верю, но это именно суббъективное чувство. У меня вот тоже от наличия тестов его не прибавляется — а только от наличия того самого «понимания кода». Тесты к нему имеют некоторое отношение, но не прямое.
+1
Как вы только что процитировали, тесты позволяют реально только продемонстрировать наличие ошибок. Но не их отсутствие. Что бы вы хотели ими продемонстрировать?

То, что код протестирован. Чем выше процент покрытия тестами, тем проще отладка. А отсутствие тестов, что демонстрирует?
откуда у вас после тестов уверенность-то возьмется +100%, что задача решена верно?

не +100%, а +100 к параметру уверенность. И не задача решена верно, а программа компилируется и запускается.
0
Чем выше процент покрытия тестами, тем проще отладка.

Смысл всей этой формальной ерунды в том, что вы формализовали спеку, доказали соответствие этой спеке, и потом вам ничего в рантайме проверять или отлаживать не надо, потому что вы уже всё доказали.

+1
>То, что код протестирован
Ну мыж только что обсудили, что это не дает гарантий? Никаких. Или вы Дейкстру процитировали, но с ним не согласны?

>А отсутствие тестов, что демонстрирует?
На мой взгляд — что кто-то дурью маялся. Не вообще, а конкретно вот тут.

Ну то есть, я хочу сказать что — бывают языки, где вы не можете доказать формально почти ничего. Бывают сложные системы, где стоимость такого доказательства запредельно велика. В таком случае я соглашусь, что лучше иметь тесты, и какое-никакое покрытие ими.

Но при возможности и наличии формального доказательства? Зачем?
0
Или вы Дейкстру процитировали, но с ним не согласны?

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

Тесты могут показать наличие ошибок, а могут и не показать, но они никогда не покажут наличие отсутствия ошибок. Акцент на второй части предложения после запятой.
Тесты практически ничего не гарантируют, кроме покрытия.
Ну то есть, я хочу сказать что — бывают языки, где вы не можете доказать формально почти ничего. Бывают сложные системы, где стоимость такого доказательства запредельно велика. В таком случае я соглашусь, что лучше иметь тесты, и какое-никакое покрытие ими.

Вот именно, дело в покрытии, а какой именно процент покрытия должен быть и на что вообще писать тесты, а на что нет — зависит от бизнеса.
+1
>Акцент на второй части предложения после запятой.
Ну я ровно так это и понимаю. Вы можете писать мало тестов, или много — но гарантии отсутствия ошибок все равно нет. При этом тесты стоят денег, и требуют времени (что где-то одно и тоже).

А тут у нас реальный, достаточно редкий на сегодня случай, когда есть формальное доказательство правильности некоторого небольшого куска кода. Ну и зачем нам вот прямо тут тесты? У нас правда нет более нужных вещей, на которые можно деньги потратить?

Скажем, запустить, и убедиться что все заработало — ну я еще могу это понять. В конце концов — померять время выполнения и потребляемые ресурсы (которые формальным доказательством не были охвачены). Ну то есть — нефункциональные тесты.
0
А тут у нас реальный, достаточно редкий на сегодня случай, когда есть формальное доказательство правильности некоторого небольшого куска кода. Ну и зачем нам вот прямо тут тесты? У нас правда нет более нужных вещей, на которые можно деньги потратить?

Насколько я понял — случай выдуманный.
Может действительно нет причин писать тест в этом случае, а может есть косвенные причины, но мы этого не знаем.
С одной стороны имеем формальное доказательство, что задача выполнена. С другой стороны, есть достаточно явное указание на то, что решение задачи не может быть верифицировано, ввиду отсутствия тестов.
+1
>Насколько я понял — случай выдуманный.
Насколько я понял, верификация обращения списка — не выдуманная ни разу.

> мы этого не знаем
Ну мы может и не знаем Idris, но это вообще-то не повод говорить, что он не работает.

У нас есть доказательство работоспособности. Правильно ли оно само — я сказать не могу, но идея доказательства по крайней мере вопросов не вызывает (что левая свертка на оригинальном списке работает так же, как правая на инвертированном). Оно использует вполне фундаментальные свойства списков, и чтобы написать любой осмысленный тест (кроме самых тривиальных), вам все равно придется такие же свойства сформулировать, и проверить, что они выполняются.
0
Ну мы может и не знаем Idris, но это вообще-то не повод говорить, что он не работает.

Мы не знаем по каким причинам интервьюер указывал на отсутствие тестов. Насколько я понимаю, прямых причин нет, но могут быть косвенные — установленные требования бизнеса, например.
+1
Вы не уловили. foldl для оригинального списка с любой функцией и любым начальным значением == foldr для инвертированного. Доказательство — это и есть тест. Берете любую пригодную функцию, и любое значение, и проверяете, что результаты идентичны. Тесты из доказательства выводятся на раз-два, по крайней мере в этом частном случае. Наоборот — далеко не так просто.
0
Я понимаю то, что бессмысленно писать тесты, если есть формальное доказательство в целях проверки кода.
Но есть и другие требования бизнеса и коммуникация с другими разработчиками, я это уже писал.
В штате компании будут работать программисты разной квалификации, да и вполне вероятно, что вы когда-нибудь уволитесь, а код-то останется.
Как ни крути, с тестами лучше, чем без тестов.

Толку-то если приняв оффер, на работе вы будете писать доказательства такого уровня, что их мало кто будет понимать. А тесты дублируют код, их почти всегда просто понять.
0
>А тесты дублируют код, их почти всегда просто понять.
Ну вот напишите (на любом удобном языке ;) тест к данному примеру? На самом деле это нифига не просто, и понять такие тесты будет не всегда просто.

>вы будете писать доказательства такого уровня
Боюсь что не будете, к сожалению. На сегодня это слишком сложно для промышленного применения.
+1
unit-test'ы — это такие неявные интеграционные тесты между компилятором, исходным текстом и ОС, где это всё запускается.

Ещё стоит добавить процессор, память и всё сопутствующее, потому что в них тоже бывают баги, необнаружимые статическим анализом кода.
+9
Ну, интервьювер по глупому сказал, чтобы вы использовали любой удобный для вас язык.

А теперь представим, что он irdis не знает, следовательно в вашем коде он разобраться не может. Если предположить. что это метаязык, суто может быть и уловит, но главное было все-таки хотя бы просто запустить на нескольких примерах, чтобы увидеть что ваша программа действительно работает.

А вы этого не сделали, тестов рабочих не предоставили, просто углубились в математические формальности.

Предположим, они берут вас на работу, и просят реализовать простую вещь. В результате получают множество раз переписанный, оптимизированный и вылизанных пулл реквест, который ни разу не запускался на локальном дев енвайрнменте, и в CI он идет без единого теста, то есть первый запуск будет где-то аж на UAT, а то и вообще в PROD?
+1
А вы этого не сделали, тестов рабочих не предоставили, просто углубились в математические формальности.

А вы правда тесты ставите выше доказательств корректности алгоритмов? Речь же не об особенностях операционной семантики языка, скажем.


В результате получают множество раз переписанный, оптимизированный и вылизанных пулл реквест, который ни разу не запускался на локальном дев енвайрнменте, и в CI он идет без единого теста, то есть первый запуск будет где-то аж на UAT, а то и вообще в PROD?

Так вакансия ж на C++ была, поэтому, увы, так не получится, придётся тесты писать :(

+3
А вы снова суть не уловили.

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

Если я не знаю вашего irdis, то формальному доказательству я может и поверю, но как я могу проверить что он правильно реализован с точки зрения кода?

Ведь нельзя сказать, что любой математик, который может формально доказать теорему пифагора, способен запрограммировать ее решение?
-1
Тесты даже необязательно писать, просто запустить программу и показать что она обратила список, который вы туда передали аргументов, или даже захардкодили.

Зачем? Какую дополнительную информацию это даёт, при условии, что вы знаете Idris?


Если я не знаю вашего irdis

А если не знаете, то какая разница, запустил я программу или нет? Может, я там в обработке нажатий от клавиатуры системную функцию reverse вызвал, а не свои эти вот, и она все ваши проверки отработает. Или захардкодил входной список и захардкодил выходной.


то формальному доказательству я может и поверю, но как я могу проверить что он правильно реализован с точки зрения кода?

А вам не надо это проверять. Реализацию проверяет сам язык (в этом вся прелесть proofs-as-terms и тайпчекинга).


Утверждение, которое доказывается, во-первых, ИМХО, достаточно читабельно. Во-вторых, даже если я сильно ошибаюсь, то чем тесты лучше? Может, опять же, я там захардкодил ответ на пару входных списков, и где-то в коде у меня что-то вроде


if input == "1 2 3" then print "3 2 1"
if input == "1" then print "1"

Ведь нельзя сказать, что любой математик, который может формально доказать теорему пифагора, способен запрограммировать ее решение?

Нельзя, конечно. Но если математик доказал, что запрограммированное решение правда решает теорему Пифагора (что бы это ни значило), то этому верить, наверное, можно, по меньшей мере, с той же уверенностью, что и тестам?

+4
С таким подходом я нисколько не удивляюсь, что не позвонили. Они просто сразу поняли весь спектр возможных проблем, начиная с межличностных.
0

А если вас попросят написать тесты для фреймворка тестов на интервью, вы это тоже с радостью сделаете или будете отказываться?


Я не очень люблю делать бессмысленные действия, и, действительно, лучше это выяснить сразу. Не назвал бы это межличностной проблемой, впрочем.

+2
А завтра вам в голову придёт, что весь продукт компании, над которым вам предстоит работать — бессмысленный. Не стоит вам с таким подходом вообще наниматься на работу.
0

Вы абсолютно правы, и вопрос о том, связан проект с какой-то ерундой, или же им заниматься интересно, он важный.


Впрочем, если уж мы заговорили об этом… Вы никогда не задаётесь вопросами целесообразности того, что вам предлагают делать?

+1
Всё не просто, а очень просто. Что-то доказывать нужно человеку, а не компилятору. Потому что именно он принимает решение и берёт на себя ответственность. И если что, фейсом по клаве будут возюкать его. Ну а потом он будут делать тоже самое с тобой. И есть вероятность, что все остальные тоже присоединятся к этому увлекательному действу. Даже те, кто плюсовал карму и ржал в комментах. Ну я вот тоже ржал — смешно же. По не позвонил бы.
Потому что вся статья это просто попытка поднять чсв за чужой счет. А нарциссизм он того — до добра не доводит. Потому что всегда нужно помнить одну простую вещь — даже теория относительности относительна.
А тут какие-то формальные доказательства, безоглядная надёжа на компилятор, и вера в постановщика задачи, ну и задранное чсв.
В общем, я бы не взял такого сотрудника, ибо страшно далёк он от реальности.
0
безоглядная надёжа на компилятор, и вера в постановщика задачи

Вера в тесты, получается, лучше?

0
Нееет, дело не в вере, а в ответственности. А ответственность на вере это такая зыбкая штука. А у тебя получается вера. Вера в формальное доказательство правильности решения, в правильность задачи, в яп, в компилятор/интерпретатор, библиотеки и тд. Вера, как известно, не приемлет логики. Критерий истины — практика. Поэтому тебя и спрашивают " где тесты, Карл?". Где результат?
«не верю (с)»
0
Где результат?

Вон терм нужного типа, он тайпчекается. Вот и результат. Вполне себе на практике.


" где тесты, Карл?"

А в чём их смысл при таких вводных-то? Ведь то, что тесты проходят, опирается на веру в компилятор/интерпретатор, библиотеки, фреймворк тестов и прочее подобное.

0
Насколько я понял Kemet и некоторых прочих комментаторов, они пытаются указать на разницу между текстом программы и собственно программой. Программа является рабочей, если она хоть раз выполнила своё предназначения, иначе она просто объект современного искусства. Так что в описанной ситуации программу стоило бы хоть раз запустить.
0

А чем запуск тайпчекера на тексте программы принципиально отличается? Вы же не маркером на доске доказательство пишете, а в виде кода в компьютере, и проверку этого доказательства в том или ином виде регулярно запускаете.

0
Сермяжностью, прикладным характером. Запустил программу — получил развёрнутый лист, программа работает. Всё предельно понятно.
0
Вы же не маркером на доске доказательство пишете, а в виде кода в компьютере, и проверку этого доказательства в том или ином виде регулярно запускаете.

Ну вот написанный код, который ни разу не был выполнен, практически ничем от написанного на доске маркером не отличается.
-1

По коду, написанному маркером на доске, тайпчекер не пробегается, и машина его корректность не проверяет.

+2
Вы, видимо, не до конца понимаете задачу тестов. Они нужны не для того, чтобы доказать корректность алгоритма, а чтобы, как минимум, обезопасить код и проект от неочевидных ошибок при изменении реализации.

Вы вот взяли и написали такой крутой алгоритм разворота списка. Доказали его формально. Залили на прод. А завтра пришел программист Вася, у которого с математикой всё не так хорошо, и добавил/изменил пару строчек. И сразу вылил, тестов же нет. А на следующий день боевой сервер упал и фирма потеряла 100500 тысяч долларов.

Любая мало-мальски крупная разработка, в первую очередь, про безопасность и тройные проверки, которые, с вашей точки зрения, бессмысленные.
0
чтобы, как минимум, обезопасить код и проект от неочевидных ошибок при изменении реализации.

«Тестирование программного обеспечения не может доказать, что система, алгоритм или программа не содержит никаких ошибок и дефектов и удовлетворяет определённому свойству. Это может сделать формальная верификация.» (С)
И сразу вылил, тестов же нет. А на следующий день боевой сервер упал и фирма потеряла 100500 тысяч долларов.

Ну если в фирме считается нормальным «сразу выливать» без пул-реквестов и код-ревью, то поделом.
+1
Ну а если код ревью может сделать единственный математик в компании, а потом он уволится, что делать?
+2

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


Доказательства — они там, рядом, в том же файле, что и основная реализация, и проверяются при каждой сборке. У вас физически не получится изменить реализацию так, что доказательство станет ложным, и при этом что-то куда-то вылить: модуль просто не соберётся.


Спасибо за ваш комментарий, я стал чуть лучше понимать суть претензий.

+6
Даже не просто overqualified, а что то уровня профессора computer science, который почему то пришёл на позицию junior programmer, с которой он сбежит на следующий же день.
0
что то уровня профессора computer science

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

+8

Кажется, я видел похожий пост, только там, как в анекдоте, не "развернуть список", а "решить FizzBuzz", и не "функциональное программирование", а "машинное обучение", и не "тесты не нужны — мы формально доказали", а "надо было взять более глубокую нейронную сеть": https://habr.com/ru/post/301536/

+3

О, прекрасно, спасибо! Я как раз, наконец, начал писать пост про формальную верификацию fizzbuzz.

+1
Разруха не в клозетах языках, а в головах! (с) Собачье сердце

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

Тот же FizzBuzzEnterpriseEdition можно переписать абсолютно на любом языке.
+4

Когда увлекаешься собственным остроумием, нужно вовремя остановиться)

+2
Вот-вот, где-то на этот счет была хорошая фраза. Что-то вроде «некоторые плохие программисты пишут код для того, чтобы каждым его символом напомнить о своем остроумии»
+3
Выражение лица интервьювера на протяжении всего собеседования:
уберите детей от мониторов

+8

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


И надо, видимо, мне потюнить свои писательские навыки, раз это можно всерьёз воспринять. Ну или не надо.

+2
Действительно можно подумать, что это произошло на самом деле, но тюнить не надо — щепотка юмора придала пикантности.
+3
На телефонных скринингах часто просят развернуть строку или список, чтобы отличить настоящих кандидатов с опытом от проходимцев, сочинивших себе резюме от начала до конца.
+5
А в чем некорректность, кстати? Интервьюер сказал — можете писать на том языке, на котором вам удобнее. Автору было удобно на Idris, в чем проблема?
+5
Как говорил Ленин: формально все верно, а по сути — издевательство.

По сути, то есть чисто с практической точки зрения, выбор технологий должен быть обоснован. Наш же лирический герой не задал ни одного вопроса на тему функциональных и нефункциональных требований для разработки и эксплуатации приложения: кто, для чего и в каких условиях им будет пользоваться. Системные требования. Требования по развертыванию и поддержке. Получив ответы можно было бы сделать логичный вывод, что выбранная технология это пустая трата времени и начать диалог по существу вакансии.
+2

Я не спорю, что по сути издевательство, в этом-то и есть весь лирический конфликт и трагедия лишнего человека, но вот


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

Это точно ожидается, когда вас просят перевернуть список или, я не знаю, проверить сбалансированность скобочного выражения?

+1
Думаю да, если речь о коммерческой разработке. Откуда берутся входные данные, упираемся ли мы в ограничения по оперативной памяти и адресации, а если упираемся, тогда что? Какие сбои и ошибки нужно отрабатывать? Как будет осуществляться приемочное тестирование? Кто будет поддерживать код, какие у них есть скиллы, какая документация нужна? — разве все это не повлияет на конечное решение, его объем и трудоемкость? Как вы оцените сроки разработки?

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

Решение такогонебыловтребованияхуменяналокалхостевсеработает это далеко не продукт. А сам такой подход к работе говорит об уровне специалиста.
+3

Кажется, я где-то видел аналогичную иронию на тему написания функции копирования файла, с уточнением требований уровня поддержки имён файлов, содержащих одновременные RTL и LTR письменности, плагинов для протоколов и подключаемых стратегий обработки ошибок. Но не суть.


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

+2
Отличная статья. Тоже читал. На мой взгляд история показывает, что невозможно найти контакт, если собеседники придерживаются граничных условий. На то они и граничные. Точки соприкосновения, общие интересы всегда где то по середине. Это и надо искать. Универсальное решение может быть неподходящим, из-за необходимости учесть множество факторов, подчас противоречивых. Грамотный инженер должен уметь получить нужные для решения задачи сведения, задав минимум вопросов по существу, а не вообще все, что может только придумать.
+17
Статья — сплошное самолюбование. Интервьюер тупой, видит код разворота списка и впадает в прострацию. Но автор — молодец, не растерялся и добил его танцем.

Что такое идрис (из коментов слово узнал), как он позволяет формально доказывать верность программ и что за навороченая систем типов у него, и т.д. так и осталось не понятным.

Вобщем, я понял только что автор владеет идрисом как чак норис пистолетом и, наверное, восхитился.
0

Не, я так себе им владею, до сих пор elaborator reflection даже не осилил.


А что за система типов — это долгая история. В пятничную статью, боюсь, не уложусь.

+7
При должном количестве усилий можно любую задачу решать бесконечно ))
+3

Двоякое впечатление на самом деле. Я сейчас работаю в большой аутсорсинговой компании и у нас есть определенный регламент интервью, который приходится соблюдать. И он даже на позицию solution architect подразумевает вопросы типа «что такое виртуальный метод?».
Но я вас прекрасно понимаю :). Поэтому заранее предупреждаю от том, что начну с детских вопросов, потому что их основная цель — снять первое напряжение на собеседовании.

+5

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

+2
У меня человек, утвердающий что хорошо знает баш, не знал что такое шебанг и код возврата.

Очевидные детские вопросы не только показывают знания человека, но также показывает как именно он на них отвечает, поэтому не обязательно искать сложные вопросы. Как раз простые вопросы могут показать как человек оперирует терминологией и понимает ли он базу.
+4

У меня как-то был собес на с++ позицию. Человек по резюме выглядел как твёрдый миддл, с претензией на сеньора. Но собеседование закончилось, когда он не смог объяснить чем ссылка отличается от указателя. Ответ «я всегда использую указатели» меня по понятным причинам не устроил.

+2
По большому счету они ничем не отличаются, по каким причинам вас не устроил ответ непонятно, если человек качественно и эффективно решает задачи только с применением указателей то в чем проблема, в данном случае вы проявили формализм, граничащий с идиотизмом.
0
Как минимум, есть синтаксические различия, и их можно было назвать.
если человек качественно и эффективно решает задачи только с применением указателей то в чем проблема
В том, что этот человек не сможет читать/понимать/поддерживать чужой код со ссылками.
0
-Чем отличается А от Б?
-Не знаю…
-Вы что, не видите, есть же синтаксические различия, А — это А, а Б — это Б. Пишутся по-разному! Как можно не видеть такую простую вещь? No hire.
+3
Но ссылки настолько core feature, что мидлу не знать её просто нельзя.

— Чем отличаются десятичные и шестнадцатеричные целочисленные константы?
— Ну, не знаю, я пользовался только десятичными…
0

Лично я бы с позиции интервьювера более чем удовлетворился бы ответом «ссылки — это указатели, которые нельзя ребиндить и которые нельзя создать неинициализированными».

+1

Проблема в том, что код построенный на указателях значительно усложняет raii подход и нужно лишний раз напрягать мозг касательно владения обьектом.
А ответ меня не устроил по той причине, что нужно хотя-бы минимально знать язык и его базовые возможности (были и другие вопросы, на которых кандидат свалился).
Если человек качественно использует только базовые вещи из си, то это вовсе не значит, что он подходит на си++ вакансию. Особенно на проект, где нормальный ООП. Ваш комментарий про формализм/идиотизм тут вообще не к месту, поскольку вы не знаете, как я провожу интервью.

0

Прочитал первый абзац, написал разворот списка на С++ со старыми добрыми указателями, а потом прочитал остальную статью и немного выпал.

+8

О, а на плюсах можно развлечься с разворотом списка типов на вариадик темплейтах в компил-тайме.

0

То есть, время компиляции в зависимости от длины списка? В рантайме-то оно, если я правильно понял идею, будет линейным (поскольку сведётся к цепочке копирований).

0
да, думаю зависит от компилятора, не уверен что стандарт такие моменты задает
0

В рантайме оно будет вообще константным, ибо темплейты — чистый компил-тайм.

+2
Слишком просто
template<class T>
struct def
{
    using type = T;
};

template<class T>
using type = typename T::type;

template<class T, class T2>
struct cat {};

template<template<class...> class T, class... ArgsT, class... ArgsT2>
struct cat<T<ArgsT...>, T<ArgsT2...>> : def<T<ArgsT..., ArgsT2...>> {};

template <class T>
struct revert : def<T> {};

template <template<class> class T, class A>
struct revert<T<A>> : def<T<A>> {};

template <template<class...> class T, class Head, class... Tail>
struct revert<T<Head, Tail...>> : cat<type<revert<T<Tail...>>>, T<Head>> {};

template <class TypeList>
using revert_t = type<revert<TypeList>>;

//check is it works
static_assert(std::is_same_v<std::tuple<short, int, long>, revert_t<std::tuple<long, int, short>>>);
+3
Двоякое чувство. Взглянем со стороны нанимателя. С одной стороны любознательность, кругозор и нестандартный взгляд на вещи это прикольно. С другой — цель технического интервью понять: интересна ли кандидату работа и будет-ли он справляться. Если нужен с++ разработчик, то не брать это вполне логичный вывод. Ведь за отведенное время соискатель не продемонстрировал ни интереса к языку, ни практических навыков. Это совсем не значит, что лирический герой не крут, просто на данную должность нужны другие супермены.
+6

Предлагаю порефлексировать и с позиции нанимающегося. Вот, например, если мне самому встать на место лирического героя, то я вспомню, что у меня в резюме примерно на второй строчке (сразу после имени) есть ссылка на гитхаб, а на гитхабе у меня довольно много кода на C++, и часть этого кода на момент написания не собиралась релизными версиями доступных компиляторов (хотя последние несколько месяцев я почти не коммичу ничего плюсового, но это неважно, там до того порядком). И если после этого работодателю необходимо, чтобы я продемонстрировал интерес к языку и практические навыки, то я могу представить следующие варианты:


  1. Работодателю, ну, просто не очень интересно. Но тогда зачем он сейчас проверяет мои навыки, если они ему неинтересны?
  2. Работодателю интересно, но у него процесс. Но это неинтересно уже мне, потому что опыт подсказывает, что у него процесс будет и чтобы жалюзи отрегулировать (нет, я не смеюсь, работал в фирме, где для этого надо заводить тикет во внутреннюю систему учёта чего-то там), и чтобы мне на этом гитхабе ещё один проектик создать.
  3. Работодатель мне тупо не доверяет, что это мой гитхаб, а не чей-то левый или что кто-то другой мне там не коммитит.

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

0
Предлагаю порефлексировать и с позиции нанимающегося.


Давайте определим цели технического интервью. Они не только в определении умения программировать. Цели:

1. Определить общую адекватность и будет ли кандидат следовать установленным правилам компании,

2. Психологическую совместимость с будущим начальникам и коллегами,

3. Умение адекватно работать с требованиями и вести диалог с «заказчиком» (даже если это тот же коллега), в том числе с закачиками, которые просят нарисовать "семь перпендикулярных линий".

4. Собственно навыки программирования,

Если ответ на любые из первых трех пунктов резко негативный, то собственно навыки программирования уже вряд ли будут иметь значение. Если на вопрос вроде развернуть список, человек встанет и уйдет, вполне очевидно ответ на первые 3 пункта будет получен за минимальное время.
+1

Предложение начать интервью с пения гимна компании справится с этим куда быстрее и эффективнее (и я знаю места, где практикуют что-то немного похожее).

+1
Это зависит от того какой психологический профиль сотрудника нужен компании (черезмерное подчинение это тоже не всегда хорошо для бизнеса), если нужен именно тот, который без возражений будет петь — попросят спеть.

Тут надо понимать, что у работодателя вполне четкие критерии, кто им нужен, поэтому сразу отсееять тех, кто по каким-то причинам не подходит — разумно.

Ну, вот возьмут они героя этой статьи, а он так же будет троллить коллег и заказчиков при реальных заданиях. Вот если бы вы были владельцем бизнеса, вы бы считали что разумно иметь такого сотрудника?

P.S. Я не говорю, что нужно у всех просить развернуть список. Я о том, что нужно понимать, что и зачем у тебя спрашивают, очень часто техническое интервью это не только и не столько проверка именно технических навыков.
+3

Про владельца бизнеса не скажу, но если бы я набирал себе команду, то списки вертеть просил бы только у джунов (и то не факт, это больно избитая задача). А там, авось, и троллить в ответ не будут.


А вопросы ведь в две стороны работают. Даже в две с половиной: они показывают не только то, кого ищет мой будущий тимлид, условно, но и с кем мне в среднем предстоит работать.

+1
Вопросы ничего не показывают. Это может быть тест на адекватность, может быть у них очень много тех кто пытается выдать себя за эксперта, может это просто вопрос для «разогрева», может в компании строгая форма интервью и т.п.
Я бы задумался, если все вопросы на интервью оказались бы такими или там начали спрашивать, что-то вообще странное вроде точной даты выпуска 1 версии Java и т.п.
+1
Поддерживаю, инженер в современном проекте должен уметь не только писать код. Софт скиллы не менее важны. Потребность в соло-разработчиках, с навыками коммуникации как у «склонного к насилию психопата, который знает, где вы живёте» (sic), даже у поддержки случается крайне редко. Троллинг как квинтэссенция формализма хорош в меру и определенных местах. На Хабре поржать, да людей в пятницу развлечь — это супер (ещё раз спасибо автору за материал). Однако выбор троллинга в качестве основного инструмента для переговоров, таких как собеседование, ну так себе решение.

Обычно начинаю интервью с внешне простых вопросов. Если кандидат в принципе адекватен, то быстро предлагает варианты. По ходу вместе с кандидатом немного меняем требования, докидываем деталей. Смотрим граничные случаи, области применимости текущего решения, возможности для расширения. Формат создаёт определенный стресс, но таковы реали итеративной разработки. Это становится отправной точкой для дальнейшей дискуссии относительно других требований, предъявляемым к сотрудникам в компании, инженерной культуре, прцессах (стек технологий, таск трекинг, quality gates, change management, документирование, ревью, тестирование, ci/cd, активности, и вот это все). Интересно наличие как общей эрудиции, так и практического опыта использования или внедрения (в зависимости от уровня и позиции).
+4
Давайте определим цели технического интервью

Определить общую адекватность

Психологическую совместимость

Умение адекватно работать с требованиями

А это точно техническое интервью?
0
точно техническое интервью

Разумеется. Кто вам сказал, что на техническом интервью проверяют только технические навыки? Вопросы, конечно, обычно технические, но по ответам и поведению практически всегда смотрят и на soft skills.

Если вы тимлид и берете человека в свою команду, то вам очень важно понимать не только умеет ли он программировать, но и впишется ли он в команду и сможете ли вы с ним работать. Это чуть ли не самые важные навыки при работе в команде.
+1
>Давайте определим цели технического интервью
>Определить общую адекватность
>Психологическую совместимость
>Умение адекватно работать с требованиями

А это точно техническое интервью?


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

При этом рекрутер такой момент проверить не может в силу отсутствия технических знаний.
+5
Я недавно был на стороне интервьювера, только по удаленке. Несколько человек тоже присылали ссылку на Гитхаб, пара человек даже в категоричной форме «если не устраивает, адьос».

Я ваш Гитхаб не видел, конечно, но вот у тех, кто присылал — просто код без комментариев, без README — непонятно, какую задачу решали. Я же хочу решение задачи увидеть — как человек мыслит, как знает свой инструмент, что у него с архитектурой.

А по такому коду могу разве что Code Style посмотреть. И что толку от этого?
+2
Я же хочу решение задачи увидеть — как человек мыслит, как знает свой инструмент, что у него с архитектурой.

Но вы ведь для этого не будете просить переворачивать списки или считать скобки?

0
Но вы говорите, что ваш код на гитхабе даже не компилится современными компиляторами…?
Получается что его ни запустить, ни отдебажить нельзя, только почитать readme?
0

Теперь уже можно (увы, ибо раньше в этом был свой шарм, когда релизный компилятор это не осиливает). Просто было время, когда C++17 (а чуть раньше — 14) уже вышел, а полноценных компиляторов к нему не завезли.


Ничего, скоро выйдет C++20, можно будет снова поупарываться.


Ну и да, для оценки шаблонной магии код запускать тоже не обязательно.

+1
Верно, я не прошу решать «задачки», но если честно, наше тестовое тоже не особо интересное. Приходится идти на эту «жертву», потому что я понимаю — никто не будет тратить пару дней на выполнение «интересного» задания. То, что даем мы — просто точка, от которой можно оттолкнуться.
0
Попробую ответить только за гитхаб) так как остальные моменты с отсутствием общих интересов очевидны — можно закончить интервью или финализировать за печенюшками на кухне и экскурсией по офису.

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

В этом плане интереснее контирбьютинг в другие проекты. Он показывает не только способность разобраться в чужом коде, предложить адекватное решение, но так же общее неравнодушие и базовые навыки коммуникации с другими людьми. Смотрю не только код, но так же внимательно читаю переписку в issue, оцениваю реакцию в комментариях к PR. По ситуации, иногда предлагал как альтернативу тестовому заданию зарезолвать ишью.
+1

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


А вот с контрибьютингом — поддерживаю, это важно. Конкретно мой гитхаб в этом плане выглядит весьма уныло, масштаба тыщи коммитов в этом году и пара-тройка ничего не значащих PR'ов да полтора issue.


+3
И если после этого работодателю необходимо, чтобы я продемонстрировал интерес к языку и практические навыки

Т.е. наниматель — редиска, потому что посмел пригласить самого Вас на позицию жалкого C++ разработчика? В некотором смысле, условная девочка из HR, которая прислала вам приглашение, немножечко не права.


Но, корректное поведение с Вашей стороны было бы проигнорировать эту вакансию. Или, возможно, потроллить рекрутера. Но если Вы согласились на интервью, а тем более пришли куда-то — то тут ваш троллинг уже совсем ни к месту. Вы приняли условие вакансии и создаете драму совершенно на пустом месте.

0

Э, почему ж редиска, если я на позицию С++-разработчика претендую?


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

+2

Гитхаб может быть набит кучей чужого кода. Резюме просто списано с первого найденного в гугле резюме.


Кандидатов обычно много и все такие замечательные. По душам поговорить про высокие материи с каждым слишком дорого. Поэтому phone screening, где вас спросят написать FizzBuzz или развернуть список — это вполне адекватно.


Вас же не бесит, что надо анкеты какие-то заполнять, CV по общепринятому стандарту делать? Ну вот решение тривиальных задачек — это еще одна бюрократическая неприятность, которую надо преодолеть.

+3
Гитхаб может быть набит кучей чужого кода.

См. п. 3.


где вас спросят написать FizzBuzz

Да без проблем!


Вас же не бесит, что надо анкеты какие-то заполнять, CV по общепринятому стандарту делать?

А какие анкеты? Единственные бумажки, которые я заполнял за последнее время — это NDA на задачки и/или проприетарную информацию, которую я могу узнать на собеседовании (второе прям даже воодушевило, это ж значит, что мы будем реальные задачи обсуждать, а не как списки переворачивать!).


А CV у меня… Ну я скачал где-то шаблон для латеха и в нём делаю.

+5
Да без проблем!

О боже ж ты мой! 450+ строк кода без комментариев! Это даже круче FizzBuzz Enterprise Edition. Стесняюсь спросить, но… Все это нужно для реализации, или большая часть — это доказательство?

0
Это даже круче FizzBuzz Enterprise Edition.

Спасибо, я старался!


Большая часть — доказательство и, ээ, формализация (ну вот что такое деление, например?), плюс вспомогательные вещи — те же натуральные числа или процедуру деления я реализовал с нуля сам. Реализация — последние 5-6 строк.

0
Большая часть — доказательство и, ээ, формализация (ну вот что такое деление, например?), плюс вспомогательные вещи — те же натуральные числа или процедуру деления я реализовал с нуля сам.
Насколько велика «стандартная библиотека» Идриса? Просто хочется из коробки иметь ряд доказанных вещей, натуральные числа своими руками это не сколько неудобно.
0

Натуральные числа и, например, их неравенства там точно есть. Формально верифицированного деления в нужном мне виде, ЕМНИП, нет.


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

+1
Я начинаю сомневаться, что 0xd34df00d разработчик.
Зачем ему вакансия разработчиков, если ему прямая дорога в прикладные математики или как это называется?

На работе обычного senior С++ разработчика, или не дай бог тимлида, он же просто перегорит от необходимости писать обычный код, без формальных доказательств, еще и писать тесты.
+1

Я, кстати, таки всерьёз подумываю в чистую математику идти. Так-то в дипломе у меня написано «прикладной математик», но там как раз всей этой ерунды с формальными доказательствами не было, увы.


Но да, то, какой код (все эти темплейты на плюсах, кстати, с тестами) и как надо писать — вполне себе послужило критерием недавнего выбора нового места работы.

+1
Хм. Знаете, это вероятно выдуманное интервью, и в реальном случае было бы примерно так (где-то посредине): «Достаточно, а теперь перейдем к технической части нашей беседы ;)». У соискателя спросили о чем-то одном. Если интервьюирующий не смог быстро оценить ответ, и перейти к следующим вопросам — это его проблемы, вам не кажется? Если ему интересны реально навыки в разработке на C++ — ну тогда не надо разрешать писать примеры на любом языке, уточнил бы сразу. Ну т.е. — ССЗБ.
+8
И не перезвонят. В резюме же было написано, требуется программист С++, а не тролль 80lv со знанием Idris :)
+4
Занятно. На Прологе через аккумулятор синтаксически покороче будет, хотя по сути то же самое:

revOnto([H|T],A,R):- revOnto(T,[H|A],R). 
revOnto([],A,A).
revAcc(L,R):-revOnto(L,[],R).


А вот «тупенький» вариант выглядит более неуклюже:

revDumb([],[]). 
revDumb([H|T],R):- revDumb(T,RevT),  append(RevT,[H],R).


Было бы, конечно, круто использовать предикаты второго порядка:

revDumb([],[]). 
revDumb([H|T], R):- append(revDumb(T, RevT), H,R).


Но доказать не могу.
0
И я. Не подскажете, языки идеологически близки, или автор Индриса не это имел в виду?
0
Я именно про идеологию. Пролог создавался с идеей, что для решения задачи достаточно описать «мир», начальное состояние и конечное желаемое состояние. Дли Идриса насколько подробно надо очерчивать сам путь от исходного к конечному состоянию?
+1

Весьма подробно.


Наверное, самое близкое к автоматическому поиску пути — поиск доказательства утверждения. У идриса из коробки для этого довольно мало средств (но есть elaborator reflection, который по факту позволяет скриптовать тайпчекер, и который я пока не осилил), и ближайшим аналогом тут скорее будут тактики из Coq.

+3
Я недавно на собеседовании со стороны работодателя задавал вот такой нескучный вопрос:

image

Два конфокальных зеркальных эллипсоида соединены зеркальным же кольцом, как показано на рисунке, внутри вакуум.
В фокусах два горячих тела Alice и Bob (не отвлекайтесь), для краткости А и В.
Все фотоны из А попадают в В, но только часть фотонов из В попадает в А, некоторые отражаются обратно в В.
В итоге имеем перекачку тепла из А в В без внешнего источника энергии, то есть вечный двигатель второго рода.

Вопрос: где засада?

Тянуто отсюда


Парень был тоже из ИТМО(как и я), очень толковый, хорошо пообсуждали. Но не прошел других коллег (они, что интересно, тоже из ИТМО).
0
Я нифига не физик, но предположу, что фотоны из A и из B будут иметь разную энергию. Соответственно, один фотон из B в А перенесет энергии больше, чем один фотон из A в B или типа того.
0

Если до начала эксперимента А и Б были одинаковой температуры, а в равновесном состоянии Б оказалось горячее А, то это означало бы, что тепло из А передалось в Б без совершения работы. Добавляя/удаляя малый полу-эллипсоид можно было бы получить постоянную перекачку тепла из А в Б и обратно, т.е. вечный двигатель.

+3
Является ли вечным двигателем маятник, перекачивающий энергию из потенциальной в кинетическую, и обратно?
0

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

+1

Тепло перекачивается из А в Б и обратно, но суммарная энергия системы остаётся неизменной. В чём заключается вечный двигатель-то?


P.S. Суть вечного двигателя — в возможности неограниченного извлечения энергии. Здесь же энергия не извлекается.

0

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

+1
Видимо, проблема в вышеприведённых рассуждениях в том, что предполагается, что энергия сконцентрирована только в точках A и B. Температуры A и B должны сравняться, а весь излишек энергии будет летать между зеркалами. При изменении геометрии что будет с теми фотонами, которые окажутся в «откусываемой» области?
0
При изменении геометрии что будет с теми фотонами, которые окажутся в «откусываемой» области?

Окажут давление на зеркало, если область именно откусывать.

0

Тогда бы и солнечные электростанции были бы нарушением второго начала термодинамики. А ведь ничего не нарушается!


Кстати, парадокс с эллипсами можно даже упростить: взять белое тело и поместить его в полость чёрного тела. Даже если тела будут неидеально белые и чёрные, белое тело всегда будет холоднее чёрного, и можно извлекать энергию из разности температур.


Парадокс же разрешается тем, что абсолютно белых тел не существует. Если тело что-то излучает, то оно должно это же излучение и поглощать, иначе получается демон Максвела.

0
  1. Открываем систему и приводим её в равновесие с окружающей средой. Температуры тел А и Б становятся равными Т.
  2. Закрываем систему, вводим малый эллипс. А остывает ниже Т, Б нагревается выше Т.
  3. Используем разницу температур A и Б для совершения работы.
  4. Повторяем до бесконечности.

Получили вечный двигатель второго рода.

0

Засада в том, что если фотон из А попадает в Б, то по той же самой траектории фотон из Б попадает в А.
Это не модель АЧТ в виде камеры-обскуры с дыркой: тут дырка будь здоров какая.


Можем посмотреть, при каких условиях наступает равновесие.
Пусть А и Б равномерно светят во все стороны.
При этом весь поток из А направлен в Б.
Некоторая доля q потока из Б направлена в А, а остальная (1-q) направлена в Б.
Тогда, если Б излучает ровно в q раз больше, чем А, потоки энергии уравниваются.


Как связаны пропорции размеров эллипсоидов и телесный угол облучения Алисы Бобом — хз, надо считать. Было бы желание.


У doctor-notes притянуты разговоры про температуру вселенной, всё такое… это совершенно избыточно.

0
Засада в том, что если фотон из А попадает в Б, то по той же самой траектории фотон из Б попадает в А.

Я не физик, но нипель для фотонов существует. Это стекло с одной стороны серебрянкой покрашеное.
0
Я тоже не физик, но идея zabbius'а мне кажется более близкой к истине.
Длина волны теплового излучения обратно пропорциональна температуре излучающего тела, и заодно энергии излучаемого фотона. Как только В нагреется выше А, он начнет излучать более синие фотоны, доставляя А с каждым фотоном большее количество энергии. При установившемся равновесии В будет горячее А, но вот посчитать это мне уже слабО.
И разумеется, это если высказанная идея верна.
0

Ну, это уже нюансы.
Главное, что потоки энергии уравновешены, а как это выражается в температуре и спектре, "оставим решить любознательному читателю".


Для модели, где оба излучателя — АЧТ, — тело Б нагреется и станет отдавать вдвое больше тепла.
Для какой-нибудь там квантовой модели, — произойдёт накачка тела Б, и оно залпом отдаст все лишние фотоны на своей частоте.
Для модели с теннисистами, — тело А кинет десять мячиков, тело Б — двадцать (десять прилетит обратно к А).

+1
При этом весь поток из А направлен в Б.

Это неверно: при конечных размерах A и Б (строго точечные АЧТ вообще не излучают) на "верхушках" эллипсоидов будут зоны, где отражённый луч будет падать обратно на излучившее их тело. Телесный угол этой зоны будет тем больше, чем ближе тело к стенке. Тело А ближе к верхушке малого эллипсоида чем Б к верхушке большого, значит А будет греть саму себя сильнее, чем Б самого себя без учёта зеркала. Зеркало восстанавливает баланс.

0

При достаточно большом размере зеркала не-точечностью источников можно пренебречь.
Конечно, телесный угол, с которого свет с поверхности А через макушку эллипсоида падает обратно на А, ненулевой, — но всё равно он маленький.
Окей, если так хочется, введите в уравнение размер этого телесного угла.


Пусть А излучает 1 единицу энергии в сторону Б и α обратно на себя.
Пусть Б излучает β обратно на себя и 1 в сторону А.
α≪β
И та самая 1 единица энергии летает туда и обратно.


σα/(1+α) — телесный угол, под которым А видно из А,
σβ/(β+1) — телесный угол, под которым Б видно из Б,
σ = полный телесный угол, 4π стерадиан

0

Ещё нужно учесть, что при конечных размерах тел все точки их излучающих поверхностей находятся не в фокусе (причём А больше не в фокусе, чем Б), и что каждая точка поверхности излучает в полусферу, а не строго по нормали, и что распространение лучей уже не такое простое, как в модели. Там такой эллиптический биллиард получается, что я не возьмусь считать всё это :)


Мне думается, что с учётом всех возможных хаотических переотражений, срез малого эллипсоида можно было бы свести к простому АЧТ, находящемуся в тепловом равновесии с Б и его излучением. Чую, но доказать не могу :)

0

Что вы спорите? Уберите зеркало совсем — оно только запутывает. Идеального зеркала не существует, равно как идеально чёрных тел, сжатых до материальной точки. Просто поместите белое тело внутрь чёрного. Не обязательно тела должны быть идеальны, главное, чтобы белое возвращало большую часть фотонов, которые прилетают от чёрного.

0

Я не уловил — что именно в указанной задаче вы моделируете белым телом внутри чёрного? А и Б — оба чёрные, и они внутри белого (зеркального эллипсоида).


Зеркала действительно просто запутывают. Кольцевое можно убрать, просто достроив большой полу-эллипсоид до полного (зеркальная симметрия). Малый полуэллипсоид, наверное, можно тоже убрать, так как неточечность тел приведёт к тому, что фотоны будут летать хаотично и заполнят всё пространство более-менее равномерно, и все эти фокусы-шмокусы не будут играть особой роли.

0

Вы еще больше упростите — 2 тела в полностью зеркальном шаре, поделенном пополам односторонним зеркалом (с одной стороны отражает много фотонов, с другой — мало. Остальное — пропускает). Тела по разную сторону от перегородки. Эффект такой же: излучение от одного тела передается другому более интенсивно, чем в обратную сторону.


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

0
поделенном пополам односторонним зеркалом (с одной стороны отражает много фотонов, с другой — мало. Остальное — пропускает).

Демон Максвелла, что-ли? :)


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

0

Таких односторонних зеркал, отражающих с одной стороны и пропускающих с другой, нет в природе, и их существование нарушило бы второй закон термодинамики. Это фактически демон Максвелла.


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

0
Я не уловил — что именно в указанной задаче вы моделируете белым телом внутри чёрного? А и Б — оба чёрные, и они внутри белого (зеркального эллипсоида).

Белое тело — тело А + зеркало, чёрное — тело Б. Мы же хотим добиться перекачки энергии из А в Б, нет?


Зеркала действительно просто запутывают.

Именно. Перекачка энергии из А в Б возможна только если температура зеркала ниже температуры в точке А.

0
Белое тело — тело А + зеркало

Если в зеркальную полость с излучением внести чёрное тело, оно войдёт в равновесие с излучением (даже если излучение изначально было неравновесным), и эта система никак не станет белым телом. Это вроде бы ещё Планк показал.


Мы же хотим добиться перекачки энергии из А в Б, нет?

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


Перекачка энергии из А в Б возможна только если температура зеркала ниже температуры в точке А.

Опять непонятно. Температура всех зеркал — ровно ноль градусов (или миллион, это неважно, так как мы их принимаем за идеальные, а раз они всё отражают, то значит ничего не поглощают и не излучают). Это никак не влияет на перекачку энергии.


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

0
Я полагаю никакой перекачки нет, ибо это позволило бы создать вечный двигатель второго рода, как я уже вам показывал.

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

0

Т.е. на тела А и Б действует сила со стороны излучения?


Если мы начнём перемещать тело А вплотную к телу Б, и поставим оба тела симметрично относительно оси симметрии зеркал, так что облучаться они будут симметрично, совершим мы при этом работу?

0
Я полагаю никакой перекачки нет, ибо это позволило бы создать вечный двигатель второго рода, как я уже вам показывал.

Ну как же нет? А я привёл в пример солнечную электростанцию. Берём тело некоторого размера с температурой 6000K, например, Солнце. Берём систему зеркал и фокусируем свет в какой-нибудь точке меньшего размера, получая температуру выше 6000K.


Опять непонятно. Температура всех зеркал — ровно ноль градусов (или миллион, это неважно, так как мы их принимаем за идеальные, а раз они всё отражают, то значит ничего не поглощают и не излучают). Это никак не влияет на перекачку энергии.

А это как раз важно. Зеркало тоже имеет тепловое излучение. Если зеркало горячее — оно будет отдавать тепло находящимся внутри него телам. Если оно холодное — оно будет отражать лучи, перекачивая энергию, при это само зеркало будет нагреваться. И так до тех пор, пока система не войдёт в равновесие.


А не нагреваться зеркало не может, потому что существование идеальных отражателей противоречит физическим законам. Если какое-то тело что-то излучает, то оно должно поглощать волны той же длины, иначе получается демон Максвела. Идеальными отражателями могут быть только тела нулевой температуры, но их не существует (впрочем, возможны варианты на квантовом уровне).

0
Берём систему зеркал и фокусируем свет в какой-нибудь точке меньшего размера, получая температуру выше 6000K.

Не выйдет — тело нагреется до 6000К и начнёт излучать навстречу зеркалам (и Солнцу) точно с такой же плотностью излучения, и всё придёт в равновесие. Зеркала не меняют спектр излучения, поэтому как был пик на 6000К, так и останется.


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

Нет тут противоречия, отражение и собственное излучение — это разные процессы. Если зеркало отражает 100%, то оно ничего не излучает и ничего не поглощает. Неидеальное зеркало можно заменить моделью из слегка полупрозрачного зеркала, нанесённого на чёрный материал, система получается неизолированной, так как зеркала будут излучать наружу своей наружней поверхностью, будет утечка. Если принять поток утечки много меньшим, чем поток обмена энергией между телами А и Б, то нас он не должен сильно интересовать, какое-то равновесие должно быть достигнуто раньше, чем утечка что-то изменит.

0
Обратно фотоны не вернутся простым путем через 2 отражения в точку В, так как должно быть 90 градусов угол в нижнем углу, а там изза скругления он не равен 90. Второй эффект в том, что объекты неточечные и свет не ходит простыми путями. Есть куча нелинейных эффектов, связанная с волновой природой света.
+1

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

+1

Вы свойства параболы и эллипса не спутали? Любой фотон из одного фокуса эллипса всегда попадает в другой фокус.

+1

А нет никакой засады. Да, в замкнутой системе тело В будет горячее, чем тело А — это глупо отрицать. До бесконечности этот процесс идти не может, т.к. чем горячее тело, тем больше энергии оно испускает, поэтому рано или поздно наступит равновесие.


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

0

Думаете, невзлетит?
Ну, давайте по-новой.


Бегущая навстречу дорожка за счёт вязкости воздуха создаёт встречный ветер.
Тяга двигателей тоже создаёт встречный ветер.
Поэтому, даже если через трение качения удалось обездвижить самолёт в горизонтальном направлении, подъёмная сила всё равно будет.
И, чем больше разгружается шасси, тем большую скорость придётся развивать дорожке, создавая ещё больший ветер.


Поэтому ситуация неоднозначная.
Если тяга двигателей маленькая, обдув крыла плохой, а трение качения большое, то дорожка может скомпенсировать тягу.
В противном случае, самолёт оторвётся.

0

А второе начало термодинамики вообще доказано? Я слышал такое утверждение, что второе начало — это никакой не закон, а лишь статистическая закономерность, не более строгая, чем "грязь обычно переходит от грязных вещей к чистым". Я долго пытался найти в интернете доказательство или опровержение этого высказывания, но ничего достаточно убедительного так и не нашёл. Вот к примеру первое начало доказано теоремой Нётер, а второе чем?

+3

Физические законы (если они внутренне непротиворечивы) не доказываются. Ставятся эксперименты с целью обнаружить нарушения закона.


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

0
Эээ, вот если бы автор комментария предоставил мне таблицу с данными реального эксперимента, то я бы принял такой аргумент. Но здесь абстрактное изображение, математическая модель, в которой свет, зеркала и эллипсы идеальны. Как только вместо реального мира мы имеем дело с математической моделью, мы попадаем в область строгой математики, а не физики.
Смотрите, рассмотрим систему следующую аксиом:
1. скорость излучения фотонов телом прямо пропорциональна температуре тела
2. фотоны излучаются телом в случайном направлении, с равномерной плотностью распределения по всем направлениям
3. Пусть для простоты все массы единичные, а тела неподвижные, и поэтому энергия тела = температура тела.
4. Когда фотон излучается, он забирает 1 единицу энергии, а когда поглощается он отдаёт 1 единицу энергии в то тело, которое его поглатило.
5. Зеркала отражают фотоны по правилу угол падения равен углу отражения.

Это — строгая математическая система. В ней второе начало термодинамики можно либо доказать, либо опровергнуть (либо это один из тех редких случаев, когда невозможно ни доказать ни опровергнуть из-за теоремы Гёделя о неполноте, но такое бывает крайне редко).
Если из данной аксиоматики не следует второе начало термодинамики, то никакого парадокса и нет, и в этой аксиоматике одно из тел действительно станет теплее другого.
Можно возразить, что данная аксиоматика недостаточно точно отражает реальный мир для решения поставленной задачи, но тогда это не загадка на логику, а тема для диссертации.
0

Не хватает дополнительного условия:
 6. Фотоны излучаются поверхностью тела. Излучение пропорционально площади поверхности и равномерно распределяется по ней.
Тогда доказательство получается достаточно простое.

+1

https://habr.com/ru/post/463957/#comment_20535187 — закон сохранения геометрического фактора. Ни одно из тел не сможет нагреть другое.


Можно возразить, что данная аксиоматика недостаточно точно отражает реальный мир для решения поставленной задачи, но тогда это не загадка на логику, а тема для диссертации.

Если добавить условие точечности тел (чтобы фотоны не промахивались мимо фокусов), то получим явно нефизическую систему, так как точечные тела с ненулевой массой/энергией будут окружены сферой Шварцшильда, и излучать будет уже она.

0

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

0
Могу предположить, что не перезвонили из-за того, что ожидали написание программы на бумаге.
0
Иногда собеседование — это просто собеседование.
HR'ы делают вид, что работают, набирая десятки резюме для конкурса, в которых победитель известен заранее, а количество интервью нужно только для отчетов и премий.
Кандидаты уже имеют хорошую работу, но периодически ходят на собеседования для поддержки знаний в тонусе, поднятие скила.
+3

Ну вот… очередной кандидат завалил простейший тест. ИТ вырождается. Нынче нормального спеца не найти.

0

И не говорите. А потом эти же кандидаты вопрошают, нужно ли высшее образование для ИТ.

+9

Я бы тоже не взял вас на работу. У каждой задачи есть область решений, приведу пример. Где-то в 6 классе я в решении квадратного уравнения написал ответ в виде комплексных чисел (в поле действительных корней не было). И потом с чувством всезнайства доказывал учительнице, что я прав. Формально — да. Фактически — это была задача на проверку конкретного набора знаний, и в этих рамках правильный ответ: корней нет. Да, можно презирать рамки и лететь в бескрайние просторы разума. Вот только я кучу времени от урока потратил на споры, вреда от того умничания было больше, чем пользы. Также и здесь: вопросы собеседования нужны для проверки знаний в области структур данных и алгоритмов. Это набор решений, применяемых в индустрии. В том числе это важно для того, чтобы ваше решение было понятно коллегам. Да, от этого отдаёт некой обыденностью, но 90% повседневных задач программиста базируются на уже известных алгоритмах и подходах. Из кубиков складывается домик. Вы приходите и приносите свои круглые кубики, понятные далеко не всем, и как бы удивляетесь, а что не так. Это высокомерно, а попросту говоря «понт».
Ещё один пример. Был у меня на работе такой же коллега, знает всё, на каждую задачу выдавал крутые презентации с кучей формул, алгоритмов, мозг! Только вот в итоге он не довёл ни одной задачи до конца, и был уволен. Он просто тонул в сложности своих же решений, деталях, там где нужно было просто взять и сделать. Его «правильное» и очень продвинутое решение занимало слишком много времени, его тяжело было поддерживать всем остальным, т.е. человек жил в своей, удобной ему реальности.

0
Где-то в 6 классе я в решении квадратного уравнения написал ответ в виде комплексных чисел (в поле действительных корней не было). И потом с чувством всезнайства доказывал учительнице, что я прав.

Я надеюсь, что учительница все же знала, что такие числа существуют?


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

Значит не такой уж и "мозг". Мозг — это способность балансирования между знаниями и практичностью.

+1
Фактически — это была задача на проверку конкретного набора знаний, и в этих рамках правильный ответ: корней нет.

Ну так вы это и показали: действительных корней нет.


Ещё один пример. Был у меня на работе такой же коллега, знает всё, на каждую задачу выдавал крутые презентации с кучей формул, алгоритмов, мозг! Только вот в итоге он не довёл ни одной задачи до конца, и был уволен. Он просто тонул в сложности своих же решений, деталях, там где нужно было просто взять и сделать. Его «правильное» и очень продвинутое решение занимало слишком много времени, его тяжело было поддерживать всем остальным, т.е. человек жил в своей, удобной ему реальности.

Ну вот, думается, уволен он не потому, что формулы-алгоритмы, а потому, что тонул и не успевал. Первично таки второе.

+3

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


Возможно, вы на столько круты, что разгон не нуждаетесь, но большинство кандидатов нервничают. Собеседование — это стресс для людей.


Или вы изначально не очень заинтересовались данной вакансией, или вас все устраивает в вашей текущей работе, а пошли скорее для внутренней галочки. И тд.
Возможно, если бы это была компания, в которую вы хотели годами, с предложением на 20-30 процентов больше от вашей текущей зарплаты, с великолепными бонусами(от наши кофе леди принесут вам свежевыжатый смузи на экологически чистых фруктах и не тяжёлой воде по утрам, до наш эксклюзивный шеф-повар приготовит авторский ужин), в шаговой доступности от дома. Ну или возможностью работать удаленно, не знаю, о чем вы там мечтаете. В команду с Тим лидом, книги которого читаете и в душе считаете кумиром. Вы бы повели себя несколько иначе на собеседовании.

0
вы рассуждаете таким образом только потому что сами не в состоянии оценить уровень знаний интервьюируемого(как, собственно, и сам интервьюер в рассказе). Это словно мало что понимающие и ограниченные школьники, собеседующие взрослого и умного человека, которым непонятно о чем им говорят, ввиду чего и нанять они способны только такого же школьника, не более, потому и вся команда у них состоит из таковых. Брать или не брать на работу специалиста определенного уровня познаний и навыков — решение конечно за работодателем, кому-то нужны спецы, а кому-то команда посредственным кодеров, зато умеющих между собой взаимодействовать. Только правда в том, что зачастую работодатель ввиду собственной ограниченности считает, что набирает команду неплохих разработчиков, а на деле это совершенно не так. Потому что оценивать должен тот, кто на голову превосходит испытуемого, а не просто а-ля «психолог-кодер», который вообще не понимает о чем речь идет(причем ни в коде, ни в психологии)
-1
непонятно, почему вы считаете хороших специалистов, которые умеют решать бизнес задачи и писать отличный код ограниченными школьниками?

Далеко не на каждой работе нужна продвинутая математика, и это никак не ставит человека выше или ниже социально. Востребованность в определенной области нужна там, где она нужна, а не везде. И если «оверинженеринг» не требуется — он просто не требуется. Не нужно обвешивать ярлыками типа «говноработа, посредственные кодеры, ограниченность» и так далее.

Оценивать должен не тот, кто на голову превосходит испытуемого, а тот, кто может оценить технические навыки, которые требуются для проекта. Если проект при этом успешен с точки зрения бизнеса — то этого достаточно.
0
потому что успешность — понятие слишком относительное. Насчет ярлыков — это метафоры, ведь как-то нужно ставить людей разного уровня мышления на соответствующее место. При бытовом общении с образованным или просто неглупым человеком возникает больше приятных эмоций, независимо от того, использует он свои познания в разговоре или нет. Поразмыслите над этим.
+1
Позволю с вами не согласиться.
Комфортно общаться с человеком на одном языке примерно одного уровня развития.
0
да, Вы правы. Но на длинной дистанции результативнее общаться с людьми более высокого уровня развития. А бизнес — это не столько про комфорт, сколько про результат все же
+1
У людей с высоким уровнем развития хватает ума общаться с собеседником на том языке, который понятен всем участникам диалога. Демонстрация высокомерности и неумения работать в команде на первом собеседовании явно не приведет к положительному результату.
+4
Ну, интерпретация более развернутого и широкого мышления как демонстрации высокомерия — нормальное явление. Зачастую подобным умозаключением ограниченные в текущей сфере люди оправдывают свое непонимание вопроса
-1
Что значит результативнее? Как вы оцениваете результативность, если конечный результат — смерть?

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

ведь как-то нужно ставить людей разного уровня мышления на соответствующее место.

Это не означает выше или ниже.
0
>> revDumb (x :: xs) = revDumb xs ++ [x]

Либо это идрис «не торт», либо данная конструкция никогда не остановится. Первый элемент списка вечно ставится в конец, после чего весь список кидается на вход функции, которая опять первый элемент ставит последним, и так до тепловой смерти вселенной.

Да, зря тесты не были запущены. И да, формально — задание не выполнено. А неформально — не выполнено со страшно умным видом.
0

Не специалист по этому языку, но, кажется, рекурсивый вызов делается только для конца списка, а потом к нему уже добавляется первый элемент в конец. Приоритет операций видимо такой. Хотя, наличие скобок сильно упростило бы понимание.

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

Ну, справедливости ради, в том же С++ тоже надо приоритеты учить. Особенно логических и битовых "и" и "или".

-1
В Хаскеле, например (а он похож по синтаксису на Идрис), есть 22 оператора с приоритетами от 3 до 9 и двумя ассоциативностями — левой и правой. Приоритетов №9 — два, №8 — два, №7 — 4, №6 — 2, №5 — 2, №4 — 8, №3 — 2. Это без учёта приоритета аргументов функции и конструкций типа &.

И это всё должен знать каждый участник команды разработки, просто что бы понимать код коллег. Без такого знания будут муки и адское затягивание сроков.

В Си-подобных языках из приоритетов, кроме стандартных арифметических, вот разве что битовые операции. И всё. Плюс обязательность использования скобок, что само по себе устраняет массу вопросов типа того, который мы сейчас обсуждаем.
+1
В Хаскеле, например (а он похож по синтаксису на Идрис), есть 22 оператора

В хаскеле сильно больше операторов, и можно создавать свои. Потенциально в хаскеле счётное множество операторов.


И это всё должен знать каждый участник команды разработки, просто что бы понимать код коллег. Без такого знания будут муки и адское затягивание сроков.

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


В Си-подобных языках из приоритетов, кроме стандартных арифметических, вот разве что битовые операции. И всё.

15. Похоже, пришло время нудного заучивания.

-1
>> В хаскеле сильно больше операторов

Речь о стандартных, поэтому не надо передёргивать.

>> Я вообще не помню приоритеты операторов

Тогда с чего вы решили, что ваш код — правильный?

>> Похоже, пришло время нудного заучивания

Убираем из этого списка скобки и прочее очевидное, получаем за исключением арифметики (включая очевидные булевы операции) в разы меньше, чем в функциональщине.
0
Речь о стандартных, поэтому не надо передёргивать.

Я вот открыл модуль Control.Arrow, который идёт в base, который идёт с де-факто стандартным компилятором, и там сходу минимум 11 операторов, а это явно даже не половина.


Да и какая разница, стандартные операторы или нет, если почти все проекты не ограничиваются стандартной библиотекой, и, соответственно, вполне могут пользоваться дополнительными операторами? Я ровно поэтому боюсь той же lens, потому что там слишком много операторов (но основная проблема в том, что они как-то не очень, как бы это по-русски-то, discoverable).


Тогда с чего вы решили, что ваш код — правильный?

На идрисе доказал, на хаскеле почти всё такое же «прочее очевидное», да и вообще просто так получается. Да и опыт подсказывает, что если приоритеты перепутать, то там несовпадение типов будет.


А кстати, когда вы на С пишете, вы точно помните весь стандарт и всю семантику абстрактной машины, чтобы быть уверенным, что ваш код правильно скомпилируется?

0
>> Да и какая разница, стандартные операторы или нет, если почти все проекты не ограничиваются стандартной библиотекой, и, соответственно, вполне могут пользоваться дополнительными операторами?

Собственно это ведь тоже аргумент против широкого использования функциональных языков. Хотя я вполне был готов успокоиться на аргументе «стандартный набор приоритетов больше».

>> На идрисе доказал

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

Не помню уж где, но про системы автоматического вывода было примерно такое упоминание — в одном случае программа была написана неправильно, доказательство показывало корректность программы, но в доказательстве была ошибка, и при этом в каких-то важных аспектах программа полностью оправдывала ожидания разработчиков.

В вашем случае не обязательно всё совпадёт так, что ожидания оправдаются.

>> А кстати, когда вы на С пишете, вы точно помните весь стандарт и всю семантику абстрактной машины, чтобы быть уверенным, что ваш код правильно скомпилируется?

В основном у меня — Java, но не суть, в любом случае я очень во многих случаях вспоминаю стандарт. Раньше было хуже (меньше помнил), но с опытом стало очевидно, что помнить нужно много, благо было время на неспешное запоминание, ведь в обычном коде нечасто используются многие конструкции, либо вообще заменяются на «безопасные» (например когда не заморачивался запомнить приоритет ++ заменял его на обычное сложение).
+1
Собственно это ведь тоже аргумент против широкого использования функциональных языков.

А возможность написания собственных функций — аргумент против использования языков, позволяющих писать свои функции?


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

Я не представляю, какое выражение, например из трёх операторов >>=, <$>, <*>, надо написать, чтобы оно компилировалось, но делало не то, что кажется при взгляде на код.


Что вы дальше доказывали при помощи идрис — точно так же зависит от приоритетов, то есть приоритеты вы и там могли попутать.

А ещё я мог попутать названия функций и написать доказательство, утверждающее что-то о константных функциях трёх аргументов вместо foldr или foldl. Почему бы не рассмотреть такую возможность?


Не помню уж где, но про системы автоматического вывода было примерно такое упоминание — в одном случае программа была написана неправильно, доказательство показывало корректность программы, но в доказательстве была ошибка, и при этом в каких-то важных аспектах программа полностью оправдывала ожидания разработчиков.

А про тесты вы чего-нибудь такого не слышали?


благо было время на неспешное запоминание

Нудным получилось-то?


В основном у меня — Java, но не суть, в любом случае я очень во многих случаях вспоминаю стандарт. Раньше было хуже (меньше помнил), но с опытом стало очевидно, что помнить нужно много

Описание ядра языка в The Haskell 2010 Language Report — порядка сотни страниц, вместе с описанием библиотек — 300. Ядро плюсов занимает чуть больше и имеет чуть больше таких вещей, как, например, UB, а вместе с библиотеками вообще переваливает за тысячу. Спека джавы занимает 600 страниц, сколько из них ядро, сколько — либы, я не могу сходу сказать, ибо не знаю джаву.


Так кому там что заучивать приходится?

+1
Так кому там что заучивать приходится?

Это Совершенно Другое Дело!

0
Ну раз уж вы решились заняться членомерством, то объясняю популярно — для освоения хаскеля нужно много больше времени, по сравнению с написанием программ на Java в стиле а-ля-бэйсик. Это следствие самого функционального подхода, который противоестественен для подавляющего большинства населения, ибо в обычной жизни люди делают шаг А, потом Б, потом В, а в функциональщине все шаги нужно сконвертировать в рекурсивные вызовы функций. И понятно, что вы опять начнёте упираться и доказывать, что рекурсивные вызовы дети знают с самого рождения, но на такой трэш я отвечать уже не собираюсь.

Ну а по поводу ваших ошибок — повторю, что вы программу не запустили, а потому все ваши доказательства обязательно (рано или поздно) приведут вас к эпическому фэйлу — вы напишите сотни страниц доказательств, а работать у вас ничего не будет.
+3
Это следствие самого функционального подхода, который противоестественен для подавляющего большинства населения, ибо в обычной жизни люди делают шаг А, потом Б, потом В, а в функциональщине все шаги нужно сконвертировать в рекурсивные вызовы функций. И понятно, что вы опять начнёте упираться и доказывать, что рекурсивные вызовы дети знают с самого рождения, но на такой трэш я отвечать уже не собираюсь.

У меня таки есть маленькая, но выборка по общению с разными не умеющими программировать людьми, от к.ф.-м.н.ов до прожжённых гуманитариев. И вот мой опыт почему-то показывает, что людям equational reasoning как-то ближе, а от императивщины у них вопросы возникают типа «вот же написано i = 1, что вообще значит i = 2, что за присваивание переменных?»


Ну а по поводу ваших ошибок — повторю, что вы программу не запустили, а потому все ваши доказательства обязательно (рано или поздно) приведут вас к эпическому фэйлу — вы напишите сотни страниц доказательств

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

+2
>> У меня таки есть маленькая, но выборка по общению с разными не умеющими программировать людьми

Ну я же говорил — каждый ребёнок с рождения мыслит рекурсиями, а как ещё доказать нужность функциональщины?

>> Так я ж не на бумажке ручкой доказываю всё же. ПруфТайпчекер мои доказательства проверяет.

Я вам уже раз сто разжевал простую истину — инструмент не знает, чего хочет программист. Но вы, конечно, можете продолжать настаивать на том, что магия вас обязательно спасёт.
+1
Ну я же говорил — каждый ребёнок с рождения мыслит рекурсиями, а как ещё доказать нужность функциональщины?

Нет, конечно же, каждый ребёнок с рождения мыслит циклами, ветвлениями и выбрасываниями исключений.


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

Безусловно, не знает, с этим никто и не спорит! Мне же даже пришлось самому сформулировать условия доказываемых утверждений.


А после этого уже чистый синтаксис.

+1
Нет гарантий, что правильно сформулированы утверждения, которые надо доказывать.

Пример: доказываем, что список А есть отсортированный спискок Б.
Незадачливый доказатель сформулирует критерии:
1. Длины списков А и Б совпадают
2. Каждый элемент списка А есть в списке Б, и наоборот
3. Последовательность чисел в списке Б неубывающая.
… И ошибётся — критерий неверный. Пусть хоть и доказан формально.

То есть, формирование утверждений для доказательств — то ещё искусство. И наделать ошибок в формулировках проще простого. Для сложной программы, в формальных требованиях к её поведению скорее будут ошибки, чем не будет.
+2

А с тестами разве проще?


Ведь чтобы написать корректные тесты, вам надо сформулировать всё то же самое. А то ну протестируете вы, что sort [1, 2, 3] == [1, 2, 3], sort [3, 2, 1] == [1, 2, 3], sort [] == [], и что? Вы ведь даже не знаете, при каких условиях на входные данные и предикат порядка ваша сортировка корректна, и можно ли её обобщить с целых чисел на, скажем, строки или флоаты (подумайте о чём-нибудь с тестами на сортриовку списков, включающих IEEE754-шные NaN или Infinity).


Просто когда вы формализованно формулируете критерии, которым должен удовлетворять алгоритм, у вас, ИМХО, больше шансов осознанно придумывать контрпримеры и их ловить. Плюс, перед вами весь инструментарий и терминология математики (и вам не придётся с нуля придумывать понятие полноты порядка, скажем).


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


Олсо, не палите плз, я как раз вчера закончил доказывать merge sort. Там, например, для перестановок, сформулированных индуктивно как


data Perm : (xs : List a) -> (pxs : List a) -> Type where
  PNil    : Perm [] []
  PSwap   : Perm (x0 :: x1 :: xs) (x1 :: x0 :: xs)
  PRest   : (rest : Perm xs pxs) -> Perm (x :: xs) (x :: pxs)
  PTrans  : (p1 : Perm xs pxs) -> (p2 : Perm pxs ppxs) -> Perm xs ppxs

есть набор


положительных псевдотестов
yes1 : Perm [] []
yes1 = PNil

yes2 : Perm [1] [1]
yes2 = PRest PNil

yes3 : Perm [1, 2] [2, 1]
yes3 = PSwap

yes4 : Perm [1, 2, 3] [2, 1, 3]
yes4 = PSwap

yes5 : Perm [1, 2, 3] [1, 3, 2]
yes5 = PRest PSwap

yes6 : Perm [0, 1, 2, 3] [0, 1, 3, 2]
yes6 = PRest (PRest PSwap)

yes7 : Perm [0, 1, 2, 3] [1, 0, 3, 2]
yes7 = PTrans PSwap (PRest (PRest PSwap))

yes8 : Perm [0, 1, 2, 3] [1, 3, 0, 2]
yes8 = PTrans yes7 (PRest PSwap)

и


отрицательных псевдотестов
no1 : Perm [] [1] -> Void
no1 (PTrans p1 p2) = case nilPerm (permSym p1) of Refl => no1 p2

no2 : Perm [2] [3] -> Void
no2 (PTrans p1 p2) = case permSingleton p2 of Refl => no2 p1

no3 : Perm [1, 2] [1, 3] -> Void
no3 p = let twoIn12 = the (Elem 2 [1, 2]) (There Here)
            twoIn13 = permPreservesElem p twoIn12
        in myAbsurdity twoIn13
  where
    myAbsurdity : Elem 2 [1, 3] -> Void
    myAbsurdity (There (There Here)) impossible
    myAbsurdity (There (There (There _))) impossible

Запускать их, впрочем, тоже не надо.

+1
Я хочу донести мысль, что формально верифицированная программа не всегда работает так, как ожидает заказчик.

Верификация — это хорошо, но она может создавать ложное ощущение безопасности.

Просто когда вы формализованно формулируете критерии, которым должен удовлетворять алгоритм, у вас, ИМХО, больше шансов осознанно придумывать контрпримеры и их ловить
перед тем, как доказывать соответствие чего-то этим спекам, я беру и пишу несколько примеров с моим интуитивным пониманием предметной области, чтобы убедиться, что спека правильно их схватывает.
То есть, примеры (тесты) так или иначе нужны. Но традиционное тестирование обходится намного дешевле, чем написание формальных спецификаций.

То есть, подход дорогой, гарантированно все ошибки не вылавливает, и, может быть, снижение процента найденных ошибок не стоит потраченных усилий. То есть, применять нужно явно не в каждом проекте. В каком-нибудь типичном энтерпрайзе и вовсе бессмысленно.
+1
Я хочу донести мысль, что формально верифицированная программа не всегда работает так, как ожидает заказчик.

С этим никто не спорит. Более того, я про это сразу и написал примерно неделю назад.


Речь о том, нужны ли тесты при наличии формальной верификации или нет. И аргументы типа «ну вы же не запускали ваш код» я, похоже, понять не могу физически.


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

О, я ожидал что-то такое :)


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


То есть, подход дорогой, гарантированно все ошибки не вылавливает

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

0
Речь о том, нужны ли тесты при наличии формальной верификации или нет
Тесты могут гораздо быстрее проверить какой-то частный случай, чем потраченное время на доказательство (которое может, внезапно, оказаться нетривиальной задачей на несколько рабочих часов).
+1

Что лишь означает, что имеет смысл максимум пару раз запустить функцию ручками в repl'е перед тем, как писать доказательства.


Ну и, например, если я пишу свою монаду, скажем, то мне проще написать доказательство, что она удовлетворяет соответствующим законам, чем тестировать это.


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

Вопрос опыта. Я так-то воннаби-доказыватель, у опытных людей это делается быстро и эффективно.

0
Ну, что ваше формальное понимание сортированного списка соответствут вашей интуиции, например.
Ну примерно так я вас и понял. Но это не отменяет требований придумывать примеры.
Наоборот, гарантированно вылавливает все отхождения от спецификации
А толку? Есть неформальная спецификация — «как должно работать» в голове людей, выплняющих проект. А есть код и формальная спецификация. С доказательством «код» просто пишется 2 раза, тем самым существенно увеличивая необходимые работы, взамен предоставляя чуть больше гарантий. В принципе, какой-то заблуждение может проникнуть и в программу, и в доказательство, если это пишется одним человеком.
+1
С доказательством «код» просто пишется 2 раза, тем самым существенно увеличивая необходимые работы, взамен предоставляя чуть больше гарантий. В принципе, какой-то заблуждение может проникнуть и в программу, и в доказательство, если это пишется одним человеком.

Э, вообще-то нет, вы что-то делаете не так, если у вас так доказательства работают. Да, реализация доказываемой функции может влиять на структуру терма с доказательством, но на тип (т. е. на формулировку доказываемого утверждения, вот это вот foldl f init (revDumb xs) = foldr (flip f) init xs из исходного топика) оно не влияет.


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

0
Но оно и в тесты тогда с тем же успехом проникнет.

Заказчик, по крайней мере, может посмотреть на тест и тыкнуть пальцем: "а почему у вас тут херня какая-то вместо правильного результата прописана?"


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

+1

А часто у вас заказчики тесты смотрят, причём интуитивно понятные для этих самых заказчиков?

+1

Относительно часто. Естественно, не по инициативе заказчика. Ответ на вопрос "это правильный результат?" обычно намного более надёжен, чем попытка сверки своих интуитивных представлений, построенных по объяснениям заказчика, с интуитивными представлениями заказчика. Второе тоже немаловажно, конечно.

0

Ну это уже зависит от предметной области.


Я когда писал компилятор для одного довольно предметно-ориентированного DSL, где из документации на язык был только user guide для пользователей этого языка, там тоже никакими спеками, естественно, не пахло, и дело ограничилось набором тестов, собранных из примеров в доке и из уже написанных целевыми пользователями программок. И это представляется вполне разумным подходом к проверке в данном конкретном случае.

0
Единственное заблуждение, которое может проникнуть — неправильное понимание программистом предметной области и решаемой задачи. Но оно и в тесты тогда с тем же успехом проникнет
Программист может неправильно сформулировать критерии, которым должен удовлетворять результат. И это проникнет и в код, и в доказательство. Но, видя примеры входов-выходов в тестах, сможет интуитивно понять, что критерии неверные.
0

Весь Java Language Spec — это именно спецификация языка, там именно правила взаимодействия исходного кода и JVM, так что на все 600 страниц под библиотеку отведён только абсолютный минимум. Не читал HLR (только открыл пару случайных глав вот прямо пока писал), но могу предположить две вещи (обе из которых могут быть неверны):


  1. JLS до таких объёмов разросся когда стали всплывать и разрешаться различные конфликты между текстами и тем, как их понимают разные JVM. Хаскель со временем тоже к этому придёт, если/когда на нём будет столько же писанины и способов запуска.
  2. Хаскель обладает меньшим количеством возможных синтаксических конструкций, и/или при этом в среднем выше уровень потенциальных читателей, то есть эти конструкции можно ещё оптимизировать, если отправить пользователя RTFM какой-нибудь матан.

Опять же, посмотрите (хоть по оглавлению, как я сделал) сколько в JLS уделено описанию синтаксиса UserTypes, и сколько — HLR. Одно описание того, что и как может скрывать, оверрайдить или оверлоадить что-то ещё в Java нужно курить сравнительно долго (хотя интуитивный подход всё равно работает чаще, чем не работает).

+2
Хаскель со временем тоже к этому придёт, если/когда на нём будет столько же писанины и способов запуска.

Боюсь, что если мы начнём сравнивать де-факто стандарт GHC и его отличия от репорта, то джава по фичам будет выглядеть вообще блекловато.


Хаскель обладает меньшим количеством возможных синтаксических конструкций

Да, тут вы в точку. Синтаксических конструкций там минимум (я бы сказал, что меньше только в лиспе и брейнфаке).

-2
>> Боюсь, что если мы начнём сравнивать де-факто стандарт GHC и его отличия от репорта, то джава по фичам будет выглядеть вообще блекловато

А вы не бойтесь, вы сравните. Раз взялись — надо за слова отвечать, правильно? Вот и выполните этот приличный по объёму труд. Потом напишете статью на хабре про ваши мега-доводы в пользу функциональщины, ну а мы вас дружно покритикуем.

Но имейте в виду — вы постоянно передёргиваете и уходите от очевидных всем доказательств в сторону каких-то произвольных измышлений, лишь бы не признавать очевидного, а потому заминусуют вас, скорее всего.

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

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

Но да, все эти тома никогда не будут написаны, в отличии от тех, кто вменяемо подходит к стандартизации языков. Ибо не заставишь тысячи подобных вам заняться систематическим и довольно нудным трудом, автоматической системы документирования для вас пока не придумали, а вручную — ну нет, это не ваш метод.
+1
А вы не бойтесь, вы сравните. Раз взялись — надо за слова отвечать, правильно?

Не помню, когда я уже успел взяться.


А вы не бойтесь, вы сравните.

Давайте начнём с аналогов таких вещей, как, например, GADTs, семейств типов, DataKinds и тому подобного.


И да, по спецификации Java — она полная.

Не нашёл там сходу таблички с operational semantics, например. Не подскажете? Или для джавы это всё нинужно, ибо это очевидно для всех с рождения?


А спецификация хаскеля — недоношеный выкидыш, из которого вырезали такие скромные запчасти, как например лямбда-исчисление

Зачем оно там?


я уж не говорю про теорию категорий.

Это хорошо, потому что непонятно, причём она к спеке языка.


Но пояснения в спеке, естественно, приводятся с активнейшим использованием терминологии и лямбда-исчисления и теории категорий и ещё множества математических теорий.

Можно пример? Особенно про теоркат, пожалуйста.


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

Не нужна там спецификация компилятора, он вполне ограничен спекой языка и семантики выполнения.


Ну и до кучи — добавьте множество подвидов хаскеля

Это каких?


всяческие расширения самого языка вне спецификации

Про расширения я как раз написал отдельно.


все их версии

У расширений нет версий.


ну а к этому, естественно, ещё и всё месиво библиотек под разные версии языка и компилятора

Зачем? Чтобы потолще вышло?


Может, все библиотеки джавы тогда добавим?


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

Где тома про джаву со всеми библиотеками для джавы?


В спеках даже JNI не описано (по крайней мере, поиск по JNI или «java native» ничего не дал), о чём вообще дальше речь?

0
Боюсь, что если мы начнём сравнивать де-факто стандарт GHC и его отличия от репорта, то джава по фичам будет выглядеть вообще блекловато

Так а я не говорил про фичи, тут многие языки будут впереди. Зато смотрите: спек Java описывает модель памяти программы (вместе с гарантиями от этой модели), и, например, обратную совместимость, включая различные виду, и что будет, а что не будет обратно совместимо. То есть там немалая часть спека занимается разрешением возможных разночтений, которые бывают у писателей на Java и писателей самой Java.


Если отбросить от комментария user_man эмоции и пассаж по описании библиотек (которого и в спеке Java точно так же нет), я вижу, что HLR это далеко не единственный источник правды — значит ли это, что не всякий текст на Haskell понимается разными компиляторами одинаково? Что насчёт обратной совместимости? Кто и какими средствами сможет гарантировать, что один раз написанная программа будет по-прежнему работать предсказуемо после обновления мажорной версии компилятора, а не станет, например, требовать значительно больше памяти? Что насчёт смены компилятора? Какие гарантии у меня есть в этом случае?

0
Для хаскеля есть две ревизии спецификации — от 2010 и от 1998 (последнее по памяти, может 99). В спецификациях есть только базовая функциональность, но и её содержимое активно ссылается на кучу математики. Всё остальное отдано на откуп расширениям, в том числе таким, которые по разному реализуются разными компиляторами. Сами хаскелисты массово предпочитают Glasgow Haskell Compiler, но помимо него есть ещё несколько популярных. При этом все расширения трактуются как полезные, развивающие язык, а их объединение потенциально должно произойти в очередном стандарте, но на самом деле много расширений успешно пережило уже две редакции стандарта и так и не было включено в их состав, просто потому, что авторы осознают вред для освоения языка от включения в стандарт множества сложных конструкций. Поэтому пока что есть относительно небольшое ядро, которое плохо документировано с точки зрения понимания реального исполнения кода, ведь исполнением занимается компилятор, а как раз его-то и исключили из стандарта. И в результате у каждого компилятора есть миллион ключей, куча поддерживаемых расширений ядра, а переход с одного компилятора на другой нереален без существенного переписывания программы (более или менее сложной, разумеется). Вообще модель исполнения хаскеля не стандартизирована, в отличии от модели JVM, и для Java — это большой плюс.

Для сравнения можно посмотреть на ситуацию с андроидом — там своя версия Java. Хотя она и очень похожая на общепринятую, но всё же есть различия, особенно по стандартным библиотекам (я уж не говорю про UI). И это всего две версии, а в хаскеле их масса, и все хотят внедрить новые экспериментальные фичи, мол мы развиваем язык. В общем хаскель, как соглашаются сами его авторы — язык для исследования вариантов функциональных языков, а не для массовой промышленной разработки.
+1
В спецификациях есть только базовая функциональность,

По сравнению с расширениями GHC, конечно, базовая. Но её более чем достаточно для написания программ.


но и её содержимое активно ссылается на кучу математики.

Вы точно не путаете с документацией на Coq, например?


Поэтому пока что есть относительно небольшое ядро, которое плохо документировано с точки зрения понимания реального исполнения кода

Я не понимаю, что вы в это вкладываете. Можете привести пример?


Вон ту же джаву возьмём — она хорошо документирована? А изменения в JIT или GC как соотносятся с документацией? Получается, она либо не документирована, либо спека часто ломается, и обратной совместимости нет?


Вообще модель исполнения хаскеля не стандартизирована

Стандартизована семантика выражений и их вычисления. Виртуальная машина не стандартизована? Так это потому, что хаскель компилируется в нативный код, и её нет (в терминах языка, конечно же: никто не мешает вам компилировать хаскель под ту же JVM, что делает Frege или Eta). Что ещё стандартизовывать-то?


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

Так берёте GHC и используете его, хоть для продакшена (абсолютно спокойно, ага, опыт есть), хоть для чего угодно.

0

JIT и конкретная реализация GC не являются частью Java — они точно такие же расширения, как конструкции у GHC (хоть я и не смогу сказать точнее ввиду отсутствия информации по GHC). Потому в JLS искать их бесполезно.
Большая часть того, что вам будет известно о GC, к примеру, заключено вот на этой странице: https://docs.oracle.com/javase/specs/jls/se12/html/jls-12.html (кстати, обратите внимание, сколько там нудятины) — в остальное время вы знаете только что он "где-то там". В самом деле, не так давно появился No-OP GC, который просто ожидает, что программа не проработает достаточно долго, чтобы отсутствие сборщика вызывало какие-то проблемы, а ОС уж соберёт после процесса как полагается.


JNI это тоже отдельная спецификация. Потому что с точки зрения языка в целом это только единственное ключевое слово, указатель на то, что реализация метода находится "снаружи". Как именно снаружи — шерифа не волнует.

-2
Я вам уже писал — вы передёргиваете, а потому не вижу смысла продолжать демагогию. Далее приведу один пример, всё остальное — аналогично.

В спецификациях есть только базовая функциональность

По сравнению с расширениями GHC, конечно, базовая. Но её более чем достаточно для написания программ.


Здесь вам указано на проблему — в спецификации нет многих нужных вещей (предвижу ваше заявление про «а что нужное, а зачем вообще что-то ещё» и т.д., но это очередная демагогия, поскольку всем ясно, что на базовом уровне качественную программу не напишешь, всегда есть потребность в дополнительных рычагах), но вы проблему игнорируете и забалтываете откровенными глупостями про «её более чем достаточно». Более чем достаточно бывает, когда ясно всё, от конкретного алгоритма, в который компилятор переведёт текст и до выделения памяти, работы с IO (до мелочей, до конкретных точек запуска относительно написанного кода) и т.д.

То есть в целом вы, игнорируя глобальные проблемы, а затем возражая детским лепетом про «а я и без этого всё могу!», уводите разговор от необходимости согласиться с наличием проблемы, при этом свешивая на оппонента все ваши детские фантазии про «вы точно не путаете» и всё в таком духе. Вам показывают большую проблему, а вы заявляете, что проблемы нет и доказываете это возражениями из серии «вы точно не путаете». То есть имеет место чистейшая демагогия, ну а с демагогами общаться — себя не уважать. Так что — адьёс.
+3
Далее приведу один пример, всё остальное — аналогично.

Изящный способ уйти от ответа на вопрос о том, нафига вообще теоркат в описании языка.


Или, например, от вопроса о том, где же в описании джавы полная операционная семантика или хотя бы описание машины Тьюринга (раз уж вы описание лямбда-исчисления в HLR требуете).


предвижу ваше заявление про «а что нужное, а зачем вообще что-то ещё» и т.д., но это очередная демагогия, поскольку всем ясно, что на базовом уровне качественную программу не напишешь, всегда есть потребность в дополнительных рычагах

Почему на базовом уровне-то не напишешь? Какие-нибудь там семейства типов или даже мультипараметрические тайпклассы совсем не обязательны для написания ПО (и, в частности, функциональщины, окамлисты и SML'щики не дадут соврать).


Откуда возникает прямо-таки потребность, например, в семействах типов или в фундепах? Да, они приятные, с ними можно писать более выразительный и безопасный код, но они не ялвяются обязательными (особенно если сравнивать хаскель не с идрисом каким-нибудь, а, скажем, с джавой).


Более чем достаточно бывает, когда ясно всё, от конкретного алгоритма, в который компилятор переведёт текст

Так это, текст и описывает алгоритм, вы ж не с аналитиком каким-нибудь общаетесь, который по нечёткому описанию задачи предлагает её решение, а вполне себе со строгим компилятором.


уводите разговор от необходимости согласиться с наличием проблемы

Да я не против согласиться-то, дело в другом. Дело в том, что по вашему определению проблемы беспроблемных языков нет — даже один из немногих ISO-стандартизованных языков, C++, например, не описывает алгоритмы, в которые переводится исходный код, ибо описывается только семантика (причём не очень формально, в стандарте есть места, открытые для интерпретации), и есть as-if rule. Так что толку от такого определения проблемы нет.

+1
я вижу, что HLR это далеко не единственный источник правды

Да, есть компиляторы, которые предоставляют кучу расширений. Но на pure haskell 2010-код это не влияет.


значит ли это, что не всякий текст на Haskell понимается разными компиляторами одинаково

Нет. Если вы не используете расширения языка, то репорт определяет поведение единственным образом.


Что насчёт обратной совместимости?

Её иногда намеренно дропают в библиотеках (applicative/monad proposal, foldable/traversable proposal, semigroup/monoid proposal). Ловится на этапе компиляции и заставляет сделать довольно синтаксический и тупой рефакторинг, ничего страшного, зато помогает держать библиотеки в чистоте и без легаси.


Различий в семантике я сходу не припомню.


Кто и какими средствами сможет гарантировать, что один раз написанная программа будет по-прежнему работать предсказуемо после обновления мажорной версии компилятора, а не станет, например, требовать значительно больше памяти?

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


Впрочем, у меня бывало, что возвращаешься к проекту через пару лет, апгрейдишь компилятор, а программа становится процентов на 30-50 быстрее ну просто вот от перекомпиляции. Не могу пожаловаться.

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

Понимаете, какая штука. Улучшение производительности — это, зачастую, тоже регрессия. Потому, к примеру, в стандартной библиотеке Java есть уже несколько версий по-разному работающих классов, абстрагирующих одно и то же, по сути. Потому, что как ни старайся — а иногда код написан с расчётом на сайд-эффекты. Плохо ли это? Разумеется. Но код работал до обновления, и там было вложенное ожидание, что некое действие займёт как минимум 13 миллисекунд, а после обновления функция иногда выполняется за 9, а значит код ломается. Вот такие вещи в Java тоже во многих случаях считаются регрессией. Если что в Haskell — не будут — то это нехорошо для развитого, устаканившегося бизнеса.

+2
код работал до обновления, и там было вложенное ожидание, что некое действие займёт как минимум 13 миллисекунд, а после обновления функция иногда выполняется за 9, а значит код ломается.

https://ithappens.me/story/9 — не из ваших кругов история, случаем?

+3

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


А если такие штуки в джаве считаются регрессией, то я правильно понимаю, что производительность джава-кода 15 лет назад и сегодня должна совпадать, и никаких оптимизаций производительности не применяется?


Если что, я таки и на плюсах иногда пишу, и вот там назвать улучшение производительности сгенерированного кода регрессией — ну, короче, ни разу такого не видел. Максимум, люди жаловались, что у них компилятор после апгрейда сломал их полный UB гениальный код.

0
никаких оптимизаций производительности не применяется?

Ну нет, зачем так категорично.
На такие случаи в Java есть модель памяти и синхронизаций, с разграничением на то, что платформа может обещать и чего не может. И если вот в модели говорится, что некое действие строго после — то хоть обоптимизируйся, но придётся потом ждать на мониторе. Зато вот там, где гарантий не давалось, будет самая мякотка. К примеру, вполне может быть, что для итерации по циклу с созданиями объектов внутри — на самом деле не будет создаваться никаких объектов, а может и итерации не будет, несмотря на то, что в исходном коде по этому поводу написано.

0
Таки что, может компилятор выбросить создание объектов, после чего
код работал до обновления, и там было вложенное ожидание, что некое действие займёт как минимум 13 миллисекунд, а после обновления функция иногда выполняется за 9, а значит код ломается
0

Именно так вот выбросить — не может (вернее, ему запрещено так делать).
Если же поведение программы после оптимизации не поменялось (X ускорилось на 4мс, но при этом и Y тоже ускорилось на [4,..)мс, так что всё равно happens-before(X, Y)) — то может, но и программа при этом не сломается. Собственно, в этом и заключается вся суть таких отношений и вообще необходимости вводить модель памяти.

0
А если X ускорилось, а Y не ускорилось, потому что для ускорения Y нужен другой тип оптимизации, либо оптимизация Y в принципе невозможна (или мешает модель памяти), то программа ломается.
0

Если мешает модель памяти, то либо ничего не в итоге ускорилось (потому что более быстрый процесс в итоге парковался и ждал более медленный), либо вам и не обещали, что это будет работать. То есть для части случаев самой спекой регламентирован ответ Won't Fix на некоторые сообщения о "багах".

0
либо вам и не обещали, что это будет работать
Вот об этом и речь! Не обещали, но криворукие разработчики заложились на то, что ф-ция X работает дольше, чем ф-ция Y. И оптимизация, разрешённая спеками и моделями памяти, таки ломает программу.
0

Ну да, а на этот случай прямо в спеке языка написано "А мы всегда говорили, что результат непредсказуемый". Вы сейчас боретесь с частью утверждения, мне кажется, тогда как исходная идея как раз состоит в том, что в спеке Java есть история многих споров между разработчиками хост-JVM и чего-нибудь энтерпрайзно-банковского. А в спеке Хаскеля, как я понимаю — этого нет, из чего я делал предположение, что там это со временем появится, если язык наберёт популярность.

0
Я борюсь с утверждением
Улучшение производительности — это, зачастую, тоже регрессия
Которое должно, на самом деле, быть сформулировано в виде «Нарушающее гарантии улучшение ...». Но нарушение гарантий — это явно ошибка компилятора, такое нельзя называть улучшением. Потому и вся фраза абсурдна.

А так, можно подумать, произвольное улучшение производительности — вред.
+1
А в спеке Хаскеля, как я понимаю — этого нет, из чего я делал предположение, что там это со временем появится, если язык наберёт популярность.

А там особо ломать нечего (в основном за счёт иммутабельности), поэтому и в спеке писать нечего.


Понятно, что кто-то может начать опираться на конкретный порядок записей в MVar общую между потоками переменную, но это ССЗБ в любом языке.


Есть ещё, кстати, куда более интересный вопрос о том, можно ли единожды вычислить список [1..n] в коде типа sum [1..n] + product [1..n] (ответ: можно, но тогда код будет занимать O(n) памяти вместо O(1), поэтому так делать не стоит, и компилятор так не делает, и именно поэтому иногда выгоднее прочитать, скажем, файл два раза и поточно его обработать, чем читать один раз и держать в памяти).

0
что кто-то может начать опираться на конкретный порядок записей в MVar общую между потоками переменную

Это всё, к сожалению, по моему впечатлению, происходит достаточно часто — когда пытаются выжать последние соки из текущей среды исполнения, там могут быть любые грязные хаки. Я, впрочем, согласен, что под такой код что-то делать в спецификации будет ошибкой — достаточно просто указать, с какого момента компилятору разрешено считать программиста "ЗБ".

0

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


Этот факт, однако, не породит отношение happens-before между ними.

0

У этих отношений в целом нет хороших примеров из взаимодействий предметов реальной жизни. Разве что-нибудь вроде испускания и регистрации фотонов в двух релятивистских системах отсчёта. И то не уверен.
Суть-то в том, что у каждого потока собственное время, которое не обязано в общем случае течь так же, как у кого-то ещё.

+1

К счастью, конструкций там не так много: вызов функции.


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


Да и, по субъективному опыту, я никаких приоритетов операторов не запоминал, и при этом почему-то проблем с этим не испытывал.

0
>> поэтому некорректный порядок поймается на уровне типов

В данном случае не поймается — на входе функции список, на выходе конкатенации тоже; на выходе функции список, на входе конкатенации тоже. То есть хоть так, хоть так — будет валидный код.
-2
Понятия не имею, что за магическая тулза имеется в виду, но компилятор — не поймает.
0

Всё же перед тем, как подобные заявления делать, стоит немножко разобраться в предмете.


%default total

revDumb : List a -> List a
revDumb [] = []
revDumb (x :: xs) = revDumb (xs ++ [x])

Type checking ./Bad.idr
Bad.idr:5:1-39:
  |
5 | revDumb (x :: xs) = revDumb (xs ++ [x])
  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Main.revDumb is possibly not total due to recursive path Main.revDumb --> Main.revDumb
0

А он в данном случае видит, что revDumb получает на вход в рекурсивном вызове список такой же длины, какой был в исходном?

+1

Нет, там всё тупее: он видит, что ни один из аргументов к рекурсивному вызову revDumb не является «structurally smaller», чем текущие аргументы. То есть, если вы напишете функцию типа


dumb : List a -> List a
dumb [] = []
dumb [x] = [x]
dumb (x :: y :: xs) = dumb $ x :: xs

то чекер не поймёт, что она на самом деле завершается, и тоже ругнётся (а вот если на последней строчке будет y :: xs вместо x :: xs, то поймёт).


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


dumb : Vect n a -> (m ** Vect m a)
dumb [] = (_ ** [])
dumb [x] = (_ ** [x])
dumb (x :: y :: xs) = dumb $ x :: xs

*Bad> :total dumb
Main.dumb is Total

Walther recursion, в общем.

0
Это же идрисовский инструмент, поэтому и не имею понятия.

Хотя да, прикрутить достижения теории рекурсивных функций к программированию с использованием рекурсивных функций — абсолютно логично. Поэтом я за такие инструменты.
+1
но компилятор — не поймает.

Это же идрисовский инструмент, поэтому и не имею понятия.

Ну ок.

+2
Либо это идрис «не торт», либо данная конструкция никогда не остановится. Первый элемент списка вечно ставится в конец, после чего весь список кидается на вход функции, которая опять первый элемент ставит последним, и так до тепловой смерти вселенной.

Применение функций всегда, во всех известных мне ML-подобных языках, имеет больший приоритет, чем любые операторы, поэтому rhs парсится как (revDumb xs) ++ [x], так что всё там в порядке. Да и в идрисе есть тоталити чекер, который на revDumb (xs ++ [x]) бы ругнулся.


Да, зря тесты не были запущены.

Эх, сколько же людей верят в тесты, но не верят в формальные доказательства.

0
Тест показал бы (не)корректность интерпретации приоритетов операций конкретным разработчиком.
0

Формальное доказательство и отсутствие ругани тоталити чекера на partiality показало это, ИМХО, лучше.

+4
Не знаю было ли в задумке автора этого креатива дать хороший прием именно для собеседующего, но он дал. Попросить реализовать несложный алгоритм, на языке по выбору собеседуемого это хороший ход, особенно если вакансия подразумевает программиста владеющего конкретным языком. Если испытуемый выбрал не целевой язык вакансии, испытующий получит интересную информации к размышлению, как о технической подготовки кандидата, так и о личных качествах.
0
>вакансия подразумевает программиста владеющего конкретным языком
Хм. И какие же выводы вы для себя сделали о технической подготовке кандидата в C++?

Скажем прямо — из текстов вакансий далеко не всегда очевидно, будет ли указанный навык (язык, платформа) единственно возможным/обязательным, или будет выбор. Зачастую и проект заранее не известен. Если интервьюер прямо разрешает писать на любом языке — демонстрация познаний о другом языке для меня лично ни о чем плохом не говорит тоже.
0

Если взять в качестве примера историю в посте, то о технической подготовке испытуемого как программиста С++ я бы сделал как минимум следующий вывод. Программист идёт на вакансию по не родному для него языку, и с большой вероятностью не любит на нем программировать. Это точно не гуру С++, и интересных решений от него ждать на этом языке не стоит, даже если выясниться, что уровень владения C++ высокий В общем сеньором только на безрыбье.

0
Что-то подобное недоORM видеть приходилось, а вот производные шикарны. :)
0
Честно говоря, не вижу, откуда вы делаете такие выводы. Что значит родной язык? Я вот писал и пишу примерно на десятках языков, довольно разных. Профессионально, то есть получаю за это деньги.

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

>даже если выясниться, что уровень владения C++ высокий
В том-то и дело, что ни одного вопроса по нему не задано. То есть эти выводы выглядят как сильно надуманные (из опыта). Как прием для оценки кандидата — да, это хорошо, но если вам интересны конкретные навыки — то лучше про них прямо и спросить. А так получается что-то типа «Ах, он любит идрис, очевидно он не гуру C++».
0
В том-то и дело, что ни одного вопроса по нему не задано.

Согласен, тут гипотетический интервьюер как-то странно спрашивает про любой язык. Формально, так можно и на brainfuck наткнуться. Обычно, если вакансия C++, то и на интервью именно C++ и просят.

0
«Родной язык» наверно не совсем к месту выражение, но я думал будет понятно. Это тот который у вас в резюме идет первым в списке ваших рабочих языков. Тот на котором вы пишите что-то свое или пробуете какой-то интересный алгоритм, если не важен выбор языка.

Да, в примере не одного вопроса по С++ не задано, и это тоже вполне логично. Мало кто осмысленно возьмет в команду тролля. Поэтому желания задавать дополнительные вопросы после такого выступления, мало у кого возникнет.
0
Попросить реализовать несложный алгоритм, на языке по выбору собеседуемого это хороший ход

Проблема в том, что кандидат не просто реализовал несложный алгоритм на языке по своему выбору, а реализовал на нем формальное доказательство работы алгоритма. Саму реализацию алгоритма сделал уже в самом конце, и то, скорее для отмашки.
То есть IMHO выполнил огромный оверинженеринг для простой задачи.
+1
Саму реализацию алгоритма сделал уже в самом конце, и то, скорее для отмашки.

Э, нет, с реализации всё и началось. В этих всех языках довольно трудно доказывать свойства функций, которые вы ещё не написали.

+1
Интересно, у меня одного впечатление, что я очередную серию «Доктор Хаус» посмотрел…
Автор препарировал интервьювера))
0

Да, странно как-то. Может действительно все заболели и этот интервьюер в предыдущие собеседования в основном сидел рядом, больше слушал, чем задавал вопросы. Обычно есть среднее время на вопрос. Если человек затупил, пошел в какие-то не те дебри, то ему задают наводящие вопросы, рассказывают ожидаемое решение или просто переходят к следующему заданию.


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

0
… давая возможность тому заниматься самолюбованием

Ну, да… И это тоже)) Но красиво написано. Есть поверие, что «вся наша деловая жизнь — это шоубизнес».
Автор талантлив))
0

Ага, красиво. Собеседование во многом зависит от умения человека говорить, один даже не все зная натрындит, а второй, будучи отличным разработчиком, тупит на лёгкие вопросы, так как не в своей зоне комфорта.


Не плохой был бы ответ в стиле: "Вы слишком круты для нашей компании". Хотя нет, наверно, сейчас за такой ответ могут и в суд подать.


Я вообще фронт, у нас нет проблем в длине массива и необходимости прибегать к спискам. Можно эмитировать с помощью вложенных друг в друга объектов. Автор, как вам js?

0
Вы мазохист?)) у автора статьи спрашивать такое!!! Сейчас начнутся размышления про слабую типизацию в JavaScript engine на сервере и кастомную компиляцию движка, чтобы убыстрить тесты на 14 ms… Не, лучше не надо.
+1
Автор, как вам js?

Сталкиваюсь только в браузере и, в общем, доволен этим состоянием дел.


Ещё завидую тем, кто на js пишет, там всё время движняк какой-то, бабелы какие-то, вебпаки, тгульпы, ангуляры, всё течёт, всё меняется. У меня бы уже голова лопнула.

+1
Охренеть сколько срача вызвал односвязный список? Интересно какой угар был бы если спросили про красно-черное дерево.
typedef struct node { node* next; int value; } *pnode;

pnode reverse(pnode list) {
  pnode p,t,n;
  for(p=0,t=list;t;t=n) { n=t->next; t->next=p; p=t; }
  return p;
}
-1
Если в вашем проекте использовался односвязный список и вам понадобилось делать его «развороты» то это хорошее подспорье отказаться от него в пользу хотя бы двусвязного списка. А так это выглядит как героическая борьба с проблемами которые сами же себе и создали.
+3
А так это выглядит как героическая борьба с проблемами которые сами же себе и создали.

Разворот односвязного списка — не такая сложная задача, чтобы значительно увеличивать потребление памяти всей программы лишь для упрощения кода ее решения (2-3 строчки с тремя переменными).


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

+1

Кроме того, в ФП-стайл-программировании с иммутабельными данными сделать двусвязный список — не очень тривиальная задача (на каком-нибудь хаскеле придётся очень активно пользоваться ленивостью и завязывать узел).

+13
— Ну, давайте для начала решим такую задачу: нужно забить гвоздь.
— Сейчас сделаю! А каким инструментом лучше это сделать?
— Каким вам удобнее.
— Так… Для начала возьмем микроскоп.
— Вы уверены, что правильно поняли задачу? На рабочем столе нет микроскопа.
— А он и не понадобиться. Я Вам теоретически докажу, что забить гвоздь микроскопом возможно.
+4

Попугай: Можно измерить твой рост в попугаях…
Удав: Как это???
П.: Сколько попугаев в тебе поместится, такой у тебя и рост!
У.: Очень надо… Я не собираюсь глотать столько попугаев!
П.: Ну, во–первых, глотать никого не надо, а во–вторых, и одного попугая хватит. Меня!

0
Один я не понял, почему
… для описания алгоритмов на списках это не лучший язык

?

И какой же лучший? Неужели Идрис?
0
Лисп, конечно. Даже само его название как бы говорит нам об этом.
+1

Полезный сигнал, полученный интервьюером минимален: "кандидат вроде бы интересуется Computer Science, дальше я не понял".
Интервьюер конечно не прав в том чтобы разрешить писать на чем угодно и молчать все собеседование, но его оторвали от работы, он может себе позволить, а кандидату собеседование обычно важнее. Ну и понимать что от вас хотят — навык нужный везде.


А тесты нужны на тот случай когда кто-нибудь в будущем "поправит" ваш код.

0
А тесты нужны на тот случай когда кто-нибудь в будущем "поправит" ваш код.

Так и доказательства тогда придётся править.

+1
I’m confident that the primary reason people try to come up with exotic answers to simple programming questions during an interview is because they feel the need to impress, or “wow”, their interviewer.

They may feel somewhat insecure about the whole situation where they’re put on the spot, so they think if they appear to be the most clever, creative and brilliant mind that has walked through the interview doors, they will be a shoo-in for the job.

OTOH, folks who don’t seem to be out to impress everyone seem to come up with simple, elegant and efficient solutions that are both readable and functionally solid for all edge cases. When going into an interview, putting yourself through the added stress of trying to force a brilliant or “clever” solution to a problem will definitely work against you.

Also, it’s always a good idea to ask clarifying questions during an interview; it shows that you are a good communicator, which is important on any team, especially software development / engineering teams.

Now, the above reasons I have discussed aren’t going to apply to everyone, obviously. It’s just a pattern I’ve noticed in myself when I was a younger, less experienced software developer in college, attempting to explain my solutions and answer simple questions in my CS classes and labs. I’m fairly confident that this is a common issue among lesser experienced programmers.

Из обсуждения задач FizzBuzz и swap variables
imranontech.com/2007/01/24/using-fizzbuzz-to-find-developers-who-grok-coding/#comment-49957
+1
Now, the above reasons I have discussed aren’t going to apply to everyone, obviously. It’s just a pattern I’ve noticed in myself when I was a younger, less experienced software developer in college, attempting to explain my solutions and answer simple questions in my CS classes and labs. I’m fairly confident that this is a common issue among lesser experienced programmers.

Ясно.


Жаль, что мотивация вроде «такие задачки задают — ну, всё понятно с ними, работать я тогда здесь всё равно не собираюсь, так что хоть в объяснении $exoticname потренируюсь» в голову не приходит.

+2
 всё понятно с ними, работать я тогда здесь всё равно не собираюсь

«то есть как это всё понятно?! то есть как это не собирается?!!! в молодой! динамично развивающейся! компании, работать в которой большая честь, между прочим!!»

0
Эм… разве мы не можем просто бежать по списку и проходя каждый элемент менять ссылку на «следующий элемент» ссылкой на предыдущий пройденный элемент? Линейная сложность, один проход по списку. Я б на java это сделал так:

static class Node {
public int data;
public Node next;
}

static Node reverse(Node head) {
Node prev = null;
for (; true;) {
Node next = head.next;
head.next = prev;

if (next == null) {
return head;
}

prev = head;
head = next;
}
}

Или я не понял задачу?
0
Эм… разве мы не можем просто бежать по списку и проходя каждый элемент менять ссылку на «следующий элемент» ссылкой на предыдущий пройденный элемент?...

Можем… но это не так весело… ну и тут автор как бы и "тонко" потроллил, опять же блеснул знаниями функциональщины, да и в математику "сбегал"...


А так то да (если in-place, т.е. не нужна копия/оригинал списка) — как ответ достаточно что-нибудь типа — "поменяем" три значения в цикле (ну и какой-нибудь простейший тест):


Скрытый текст
class Node:
  @staticmethod
  def reverse(head):
     prev = None;
     while head:
       head.next, prev, head = prev, head, head.next
     return prev
  ##
  def __init__(self, d=None, next=None):
    if hasattr(d, '__iter__'):
      n = self; prev = None
      for d in d:
        n.d = d
        if prev: prev.next = n
        prev = n
        n = Node()
      prev.next = None
      return
    self.d = d; self.next = next;
  def __repr__(self, aslist=False):
    n = self;
    s = []
    while (n):
      s.append(n.d);
      n = n.next;
    return s if aslist else str(s)
  def __eq__(self, lst):
    if isinstance(lst, Node): lst = lst.__repr__(True)
    return self.__repr__(True) == lst

def test_reverse():
  assert(Node.reverse(Node([1])) == [1])
  assert(Node.reverse(Node([1,2,3])) == [3,2,1])
  # in-place change:
  n = Node([1, 2, 3, 4])
  assert(n == [1, 2, 3, 4])
  m = Node.reverse(n)
  assert(m == [4, 3, 2, 1])  # m is inversed list now
  assert(n == [1])  # n is single (last) element now
  Node.reverse(m) # n will be restored to original
  assert(n == [1, 2, 3, 4])

0xd34df00d а кстати чому idris? (и да я знаю про https://deque.blog/2017/06/14/10-things-idris-improved-over-haskell/ и т.п., но все же оно де-факто никак не стандарт, тем паче если собеседование не про pure functional lang, или я таки отстал от жизни)?
Или то из оперы — если уж троллить, то с музыкой? :)

+1
каюсь, не заметил тега «ненормальное программирование», не понял что сарказм))
+1
а кстати чому idris?

Хаскель для доказывания вещей слабоват, Агда меня юникодом пугает, Coq я пока не осилил (и не большой фанат тактик, доказывания в стиле ФП мне больше по нраву), а всякие там Isabelle — совсем другой стиль.


Так что щито поделать.

0
Да, на этой планете явно что-то не так, когда человек с такими знаниями вынужден искать работу на C++.
Были бы инвестиции я бы вас таких собрал и посадил бы делать какие-то общественно-важные проекты, вроде децентрализованной системы голосования для прямой демократии.
+2

Я уже. Но академические успехи у меня были не блистательные (GPA так себе), да и 5 лет уже с выпуска прошло, в академию надо как-то с другой стороны заходить будет.

+2
ну я надеюсь ты напишешь статью о децентрализованной системе голосования (хотя бы на уровне спецификации), конечно же формально верифицированной, хотя это не совсем наука, но что-то близкое, а главное могущее вызвать интерес сми, а значит и цитирование.
0
Кстати, в чистой математике полно работы на тему алгоритмов голосования, чёртов Эрроу всю малину испортил.
UFO landed and left these words here
-2
У меня стаж 20+. Периодически провожу собеседования на позиции C++.
Я бы вас не взял.
Во первых, все сказанное вами не имеет никакого отношения к C++.
Во вторых. Мне бы хотелось увидеть в решении такой задачи понимание следующих вещей:
а) классы, разграничение доступа, темплейты, работу с указателями. (Junior grade)
б) многопоточность, понимание атомарных операций, объекты синхронизации. (Mid grade)
г) а что если объекты списка являются экземплярами динамически порождаемых классов, например, boost_python и хранятся на разных вычислительных узлах сети и их узел зависит от места или соседа в списке? (Senior grade)
+3
Во первых, все сказанное вами не имеет никакого отношения к C++.

А вы бы ответили, что язык для решения задачи можно взять любой? Чувак в рассказе вот ответил.


понимание атомарных операций

Это локфри-список на собеседовании, что ли, или вы предлагаете свои мьютексы поверх спинлоков писать?


Если да, то это не на мида, и даже не на любого синиора.


а что если объекты списка являются экземплярами динамически порождаемых классов, например, boost_python и хранятся на разных вычислительных узлах сети и их узел зависит от места или соседа в списке?

Тогда надо сначала определиться, какие эффекты имеет разворачивание списка в этой среде.


А вопросы по распределённым системам — это, ну, тоже не на любого синиора (равно как и вопросы консистентности, атомарности и прочие двухфазные коммиты не особо привязаны к языку).

+1
А вопросы по распределённым системам — это, ну, тоже не на любого синиора (равно как и вопросы консистентности, атомарности и прочие двухфазные коммиты не особо привязаны к языку).

Конечно. Это же любой мидл знает!

+1
а что если объекты списка являются экземплярами динамически порождаемых классов
А можно привести простейший пример «динамически порождаемого класса C++»?
0
Класс С++ не упоминался комментарии. Более того, сразу же идёт пример «например, Boost.Python». Задача в том, чтобы на плюсах развернуть список, созданный в питон-программе.
0
Задача в том, чтобы на плюсах развернуть список, созданный в питон-программе.
А в таком варианте постановки задачи «Senior grade» разработчик не должен находить, что с пирогами из франкенштейна можно очень быстро получить несварение, и что питоний код должен сам предоставлять функцию реверсирования своих списков (особенно если это какие-то сложно-живущие питон-объекты), которую и можно будет вызывать из C++ для получения результата? Где-то в его опыте «20+» должен иметься такой пункт.
+1

Ну, всякое бывает нужно. Но это очень сильно неуниверсальный вопрос, и лично я бы очень сильно удивился, если бы мне его задали (хотя у меня даже в резюме упоминание Boost есть, правда, за ним следует упоминание MPL, Fusion и Hana, а вот упоминания питона нет вообще).


То есть, понятно, что этот вопрос можно интерпретировать как очень открытый, что кандидат начнёт спрашивать, как устроен Boost.Python, как устроены объекты в питоне, и так далее, но как-то это всё равно странно. Непонятно, что этот вопрос проверяет, ибо частностей слишком много.

0
питоний код должен сам предоставлять функцию реверсирования своих списков
Может он собеседуется в Лабораторию Касперского и там требуется, чтобы зловред на C++, инжектированный в программу-жертву, выпотрошил из неё данные )))
0
Pyhon тут для примера. Подобные задачи возникают очень часто в MMO играх. Движок, сеть, графика пишутся на C++. А иговая логика на Lua, Pyhton и так далее. В ММО приходится обрабатывать деревья объектов на разных физических узлах. Иногда это просто синхронизация. Иногда более сложные алгоритмы.
Only those users with full accounts are able to leave comments. , please.