Size: a a a

2020 November 02
Блог*
На случай, если нужно будет кому-то рассказать, как состоят дела у C++ с неопределённым поведением. Ребята провели большую работу по собиранию и классификации разных случаев, но не гарантируется, что этот список полный.

www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1705r0.html
источник
2020 November 03
Блог*
Excel и потерянные деньги💸
Исследования показывают, что около 90% электронных таблиц содержат ошибки. Только малая часть из них критична, но может привести к многомиллионным убыткам если их вовремя не обнаружить.

- 16 тысяч covid случаев в Британии не было зарегистрировано из-за того, что разработчики экспортировали данные в устаревший формат xls, который ограничен по количеству колонок.
- Производитель марихуаны Canopy Growth переоценил квартальную прибыль на 47 миллионов долларов из-за неправильной формулы в Excel которая считала разницу расходов и доходов.
- Boeing слил личные данные сотрудника в скрытой колонке таблицы.
- 10 тысяч несуществующих билетов было продано на Олимпийские игры в Лондоне. Всё из-за того, что сотрудник написал в таблице 20000 вместо 10000.
- Электроэнергетическая компания TransAlta потеряла 24 миллиона долларов, потому что приобрела больше договоров хеджирования чем нужно. Сотрудник компании использовал Excel функцию cut-and-paste, но неправильно выровнял ряды.
- Инвестиционный банк Lazard Ltd недооценил SolarCity на $400 млн., консультируя их при выкупе компанией Tesla, так как неправильно посчитал входные данные используя формулу Excel

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

А есть такие же консультанты, которые посмотрят на код и скажут, что в будущем эта строчка будет стоить нам миллионных убытков? Я бы нанял
источник
Блог*
#prog #python #article

Статья (в двух частях: первая, вторая), которая наглядно показывает слабость тайпчекера Mypy и проблемы с производительностью строк в Python. А, и ещё это статья о конструировании парсер-комбинаторов на Python, но это уже вторично.
источник
Блог*
#meme
источник
Блог*
источник
Блог*
#prog #idris

Статья о том, как написать на Idris аналог dataframe и типизировать для него операцию groupBy
источник
Блог*
#prog #rust #meme
источник
Блог*
источник
Блог*
Что вам надо больше?
Анонимный опрос
68%
Миллион долларов
32%
Generic associated types
Проголосовало: 217
источник
2020 November 04
Блог*
dereference_pointer_there
#prog #rust

Поясню на практическом примере, почему нужны generic associated types. Посмотрим на трейт std::io::BufRead. Это трейт, который расширяет функционал std::io::Read функционалом, который слишком неэффективно реализовывать напрямую на методах, предоставляемых Read. Подразумевается, что тип, реализующий BufRead, имеет некоторый внутренний буфер, доступ к которому можно получить при помощи fill_buf. Наличие этого внутреннего буфера позволяет реализовать некоторые операции, которые затруднительно реализовывать непосредственно поверх Read, например, read_until.

Один из методов, предоставляемых BufRead — это lines, который возвращает итератор строк. Но что именно возвращает этот итератор? Он возвращает Result<String, std::io::Error>. То есть каждый вызов Iterator::next выделяет память в куче под строку. Как-то не zero cost. В конце концов, у типа, реализующего BufRead, есть некий внутренний буфер, так почему нельзя возвращать ссылку на него? Давайте посмотрим внимательнее на типы.

Метод Iterator::next имеет следующую сигнатуру:

fn next(&mut self) -> Option<Self::Item>;

Обратите внимание: несмотря на то, что в next неявно входит лайфтайм, этот лайфтайм отсутствует в возвращаемом типе! Это означает, что значение, возвращаемое next, может быть, и не владеющее, но оно по крайне мере точно ничего не заимствует из self. А как должен выглядеть гипотетический next у нашего итератора, который возвращает ссылку на внутренний буфер?

fn next<'a>(&'a mut self) -> Option<&'a str>;

(Я сейчас намеренно опускаю вопрос об ошибках, потому что это не главное в том, что я хочу донести). Чем эта сигнатура кардинально отличается от Iterator::next? А тем, что (я даже специально расписал лайфтаймы, чтобы это было видно более ясно) возвращаемое значение заимствует self! Таким образом, даже не смотря на то, что технически мы можем написать этот метод, он не подходит под сигнатуру Iterator::next, а значит, мы не можем использовать все эти полезные итераторные комбинаторы.

Как мы можем обойти эту проблему? Вот тут и вступает в дело generic associated types. Мы можем написать альтернативное определение итератора:

trait AnotherIterator {
   type Item<'a>; // обратите внимание: тип параметризован
   fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
   // комбинаторы поверх next
}

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

Погоди, но вроде это можно реализовать и без GAT с таким определением:

trait OneMoreiterator<'a> {
   type Item;
   fn next(&'a mut self) -> Option<&'a Self::Item>;
}

Можно. Но это решение обладает рядом недостатков. Первое: его неудобно использовать на практике. Так как нужный нам лайфтайм 'a, скорее всего, будет локальным, а не обобщённым параметром, нам придётся использовать HRTB и писать что-то вроде

fn do_stuff<I>(iter: I)
where
   I: for<'a> OneMoreIterator<'a>,
{
   //...
}

Во-вторых — и это уже куда как более сильное ограничение — данное определение позволяет возвращать из next лишь ссылку на Item, а не произвольный тип, параметризованный лайфтаймом (скажем, я могу себе представить тип, реализующий AnotherIterator и возвращающий MutexGuard). В качестве примера, демонстрирующего оба недостатка, можно назвать WindowsMut, несуществующий пока аналог Windows, возвращающий перекрывающиеся мутабельные подслайсы исходного слайса.
источник
Блог*
#prog #meme
источник
Блог*
Профессионализм
источник
Блог*
dereference_pointer_there
< мем из профунктора

Я сгорел, ведь правильно приготовленный type-driven design оберегает от кучи логических ошибок, особенно связанных с проверками инвариантов (пресловутый is_initialized() вместо типа, который гарантирован находиться в валидном состояннии всегда).

Рекоммендую прочитать Parse, don't validate, или ее растоадаптацию для хабра.
#prog #article

Продолжение темы от того же автора: Names are not type safety.
https://lexi-lambda.github.io/blog/2020/11/01/names-are-not-type-safety/
В рассуждениях автора легко провести параллели с тем, как использовать и ограничивать unsafe-код в Rust.
источник
2020 November 05
Блог*
Я:
— Я взрослый мужчина, у которого есть работа и который знает цену деньгам, и я не буду делать импульсивных покупок.

Также я:
источник
Блог*
— БОЖЕЧКИ КАКАЯ МИЛАЯ ПЛЮШЕВАЯ АКУЛА
источник
Блог*
#prog #cpp #meme
источник
Блог*
Да.
(via)
источник
Блог*
#prog #article

Статья об открытой рекурсии — инструменте, который является по-настоящему уникальной особенностью ОО языков.
источник
Блог*
#prog #rust #csharp #article

Статья о взаимной интеграции кода на C# и Rust. Спойлер: работает, но выглядит (на мой взгляд) шатко
источник
Блог*
Онлайн-инструмент для просмотра диффов между текстами, изображениями, PDF и листами Excel.
https://www.diffchecker.com/
источник