Блог* – Telegram
1.9K subscribers
3.46K photos
135 videos
15 files
3.69K links
Блог со звёздочкой.

Много репостов, немножко программирования.

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
Но и в чисто прикладных вещах этот тезис получает своё подтверждение. Лично мне на ум приходит понятие итераторов (на всякий случай: сказанное ниже в основном относится к external iterator). Казалось бы, операции типа map, filter и fold/reduce куда проще определить непосредственно на коллекциях (и, собственно, в Javanoscript и Kotlin так и делают). Понятие итератора уже является некоторой абстракцией, полезность которой не ясна с первого взгляда, а уж комбинатор итераторов является абстракцией высшего порядка: он принимает итератор на вход и выдаёт итератор на выход. Казалось бы, к чему эти усложнения, почему нельзя обойтись монолитными операциями? В пользу итераторов есть несколько аргументов (впрочем, сильно завязанных друг на друга):

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

Выразительность: с помощью итераторов можно выразить то, что невозможно выразить на ограниченном наборе монолитных операций. Например, имея на руках map, невозможно в его терминах выразить операцию zip, для которой требуется перебирать последовательности синхронно друг с другом. Имея абстракцию итераторов, можно написать zip самостоятельно, в случае же с монолитными операциями мы вынуждены внести в набор примитивных операция zip... Для каждой пары коллекций! Другой пример — раннее прерывание итерации по какому-то условию. Опять-таки, вызывающий код контролирует, когда итератор выдаёт элементы, и потому ничто не мешает ему самостоятельно принимать решение, когда итерацию прерывать (и начинать ли её вовсе). В случае с монолитными операциями нет никакой возможности вклиниться в процесс итерации. Также можно упомянуть операции над данными, которые материализуются на лету, например, вычисляются или считываются по сети. Для таких источников операция map, сохраняющая тип "коллекции", попросту не имеет смысла, итераторы же работают с этим без проблем.

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

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

===

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

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

В современном изложении планиметрии эту аксиому обычно заменяют эквивалентной аксиомой о параллельной прямой:

В плоскости через точку, не лежащую на данной прямой, можно провести одну и только одну прямую, параллельную данной.
👍4🔥1
Хоспаде, изначально я хотел этот пост написать сразу после публикации того видео от 3b1b. Почему на это ушла целая неделя?
👎1
Forwarded from ТГ Шевченка
11😁4
😭
😢25😁2
#prog #rust #rustlib

smart-default

Custom derive for automatically implementing the Default trait with customized default values:

#[macro_use]
extern crate smart_default;

#[derive(SmartDefault)]
enum Foo {
Bar,
#[default]
Baz {
#[default = 12]
a: i32,
b: i32,
#[default(Some(Default::default()))]
c: Option<i32>,
#[default(_code = "vec![1, 2, 3]")]
d: Vec<u32>,
#[default = "four"]
e: String,
},
Qux(i32),
}

assert_eq!(
Foo::default(),
Foo::Baz {
a: 12,
b: 0,
c: Some(0),
d: vec![1, 2, 3],
e: "four".to_owned(),
},
);
👍9🤔3👎2🥴2😁1
Оказывается, механизм разрешения зависимостей из Poetry можно использовать для решения судоку. И судоку, и разрешение зависимостей — это задачи удовлетворения ограничений (constraint satisfaction problem), поэтому достаточно лишь записать правила судоку в виде пакетов с зависимостями и заставить Poetry это установить. А если добавить флажки для подробного вывода, то Poetry еще по пути будет объяснять, почему он решает судоку именно так. Офигенно!

Статья | Тред на реддите
🔥17👍21👎1
👎1
Forwarded from homo notes
Еп
14😢1
#prog #parsing #rust #rustlib

Chumsky

A parser library for humans with powerful error recovery.

Пример парсера brainfuck:

use chumsky::prelude::*;

#[derive(Clone)]
enum Instr {
Left, Right,
Incr, Decr,
Read, Write,
Loop(Vec<Self>),
}

fn parser() -> impl Parser<char, Vec<Instr>, Error = Simple<char>> {
recursive(|bf| {
choice((
just('<').to(Instr::Left),
just('>').to(Instr::Right),
just('+').to(Instr::Incr),
just('-').to(Instr::Decr),
just(',').to(Instr::Read),
just('.').to(Instr::Write),
bf.delimited_by(just('['), just(']')).map(Instr::Loop),
))
.repeated()
})
}
🔥12
Зачем борода вообще растёт на шее ААААААААААААААА
🤨12🌚6🤔3🤬2
🤡2👎1
👎1
🤣202🥰1👏1🤯1
#tips

Скрытый текст в телеграме можно делать не только через меню, но и обрамляя текст || с каждой стороны
👍131👎1🔥1