Тема: Декомпозиція
Під час вивчення rust-а стикнувся із психологічною проблемою.
Ще в школі я добре засвоїв принцип алгоритмічної декомпозиції: складну задачу розкладаємо на ряд простих, розв'язуємо кожну з них - і задачу вирішено. Найпростіший варіант, для задач шкільного рівня - просто записуємо умову в код і переписуємо її, доки воно не запрацює. Додати процедури? Відстежуємо в тексті дієслова і додаємо відповідні процедури/функції. Об'єктна декомпозиція? Та те саме, тільки для іменників. Не все можна зробити оптимально, але в цілому виходить непогано.
А тепер - те, що у мене не виходить. rust - мова з потужною функціональною парадигмою, і там найефективніші конструкції виглядають як довгі ланцюжки методів, на кшталт
statistics.iter()
.map( |hashmap| hashmap.iter()
.min_by_key(|tuple|tuple.1)
.map(|tuple|*tuple.0)
.unwrap() )
.collect()
Тут маємо зовнішній ланцюжок statistics->iter->map->collect (якщо записувати "класичними" функціями, то collect (map(iter(statistics),lambda))).
і в другому параметрі map - лямбда-вираз з ланцюжком hashmap->iter->min_by_key->map->unwrap. І так, там ще дві лямбди всередині.
В цілому ж ця конструкція знаходить в масиві словників ключі із мінімальними значеннями в кожному словнику. Приблизно так:
(масив)statistics: з_кожним:
перетворити( словник: з_кожним:
знайти мінімум (значення),
взяти відповідний ключ,
обробити можливу помилку ),
зібрати докупи
Але у мене не виходить це писати одразу. Доводиться писати щось традиційне, з for-ами і додатковими змінними, і тільки коли воно починає працювати, я бачу, як його згорнути в оцю функціональщину. А потреба внести зміну в цей ланцюжок часто призводить знову до розгортання в лінійний код.
Питань, власне, два:
- чи з часом моє сприйняття зміниться? Або в інших людей, що програмують на функціональних мовах, схожі проблеми?
- чи існує методика декомпозиції задачі в функціональний код?