5. Функции и итераторы. Программирование на Rust (весна 2019)
Пятая лекция курса «Программирование на Rust» (весна 2019).
Преподаватель - Алексей Александрович Кладов.
Страница лекции на сайте CSC: tinyurl.com/csc-rust-5
Ссылка на материалы: github.com/matklad/rust-course
Все лекции курса: bit.ly/2QfWama
Пікірлер: 38
Каждый раз, когда Алексей спрашивает "Ну, все здесь понятно", я отвечаю: "Нет, дядь, ниче не понятно, давай по новой" и перематываю на 2 минуты назад
@TheRussificator
Жыл бұрын
а я весь плейлист пересматриваю по два раза, и не всегда помогает)
Алексей, смог заразить меня этим языком, за что я ему благодарен. Пожалуй, это лучшие лекции, которые я когда-либо видел
Я программирую на раст уже больше чем пол года, но после этих лекций столько пробелов закрыл :) Смотрю на фоне когда прогаю -- очень толково и понятно рассказано!
Все равно осталась какая-то недосказанность по поводу FnOne, FnMut, Fn. Что они в отдельности означают понятно, но выбор их выбор компилятором и примеры плохо раскрывают тему/ Алексей, можете выпустить более полный обзор?
Хотелось бы ещё услышать про тип array. Для меня было необычно узнать, что тип array реализованый для некоторых трейтов, не может содержать более 32 элементов в себе. Будет ли лекция по std?
@nekosora6036
2 жыл бұрын
Раньше реализация трейта для массивов выглядела так: impl Trait for [T; 0] .. impl Trait fot [T; 1] .. и т.д. То есть нужно было явно указывать для какой длины массива реализуется трейт. Но написать бесконечное количество реализаций невозможно, нужно будет когда-нибудь остановиться. Вот на числе 32 и остановились. С добавлением в язык const generics можно абстрагироваться от любой длины массива: impl Trait for [T; N] .. Так что в текущей версии компилятора ограничений на реализацию трейтов для массивов - нет
40:05 видимо имелось ввиду не по ссылке, а что все мувается внутрь?
@alekseykladov1144
5 жыл бұрын
Именно так. В английском языке для этого есть точное слово consume: closure move consumes environment.
о, кружка из второй лекции
@oriontvv
2 жыл бұрын
смували по значению
А почему фолдом не пользоваться?)
Алексей, а как вернуть из своей собственной функции std::iter::Map? Что мне указать в качестве F? Замыкания имеют уникальный и безымянный тип, который нельзя произносить, а компилер требует от меня что-то указать. fn myfunc() -> std::iter::Map
@vlad071096
5 жыл бұрын
Используйте return type polymorphism.
@Uni-Coder
4 жыл бұрын
Единственное, что там прокатило - impl Iterator (это рассказывается на 7-й лекции). Но есть еще несколько важных вещей об итераторах: 1) Итератор гарантирует, что каждый элемент коллекции будет пройден не более чем 1 раз. Поэтому итератор не умеет двигается назад, а также DoubleEndedIterator - это не итератор который ездит в две стороны, а по сути это два итератора, один идет с начала, другой с конца, и итерация заканчивается, когда они встретятся. 2) О трудности реализации итераторов, которые итерируются не по значениям, а по ссылкам, и особенно по &mut ссылкам. Я перерыл массу источников, особенно англоязычных, и выясняется, что сделать это без unsafe невозможно. Я бы еще добавил про функции. Есть Fn (FnOnce, FnMut) - это по сути не функции, а замыкания. А есть еще fn, с маленькой буквы. Вот это - действительно функция. И fn с фиксированными параметрами и возвращаемым типом является _типом_ , а не _трейтом_ . Напр. тип fn(usize) -> usize.
У меня теперь куча вопросов может кто нибудь раскрыть тему. Почему у каждой функции свой уникальный тип, зачем это нужно? Почему он ещё и "неописуемый", что усложняет жизнь ещё больше. Лектор говорит тчто это трейд офф, но какие плюсы это даёт я лично не понял
@alekseykladov1144
Жыл бұрын
Хороший вопрос -- это нужно, чтобы компилятор мог хорошо оптимизировать high-order code. В итрераторе вроде `Map` когда на месте F стоит что-то вроде "тип функции foo из строчки 42", компилятор знает, какя функция будет вызвана в .next, и может её зайнлайнить в next. Если бы в Map у нас был не тип одной конкретной функции, а просто указатель на произвольную функцию, то компилятору было бы не понятно, что инлайнить. Про это можно ещё думать так -- если `F` это тип функции, то это zero-sized type, в рантайме он не существует. Он нужен только во время компиляции, чтобы обяснить компилятору статически, какой код нужно вызвать. Неописуемость это не фундаментально: можно было бы придумать какой-то синтаксис, чтобы написать тип именновыных функций, и на практике это иногда нужно, но достаточно редко, поэтому не сделали. С типами лямбд сложнее -- там не очень понятно, как назвать ёё тип. Вообще, это правда такая штука которую не так просто осознать, но зато, поняв, сразу становится понятно как Rust в целом работает. Так что да, помедетировать над формой API для итераторов в Rust очень полезное упражнение. Если понять, почему метод .map возвращает структуру Map, в которой замыкание уходит в параметр типа, много чего становится понятно doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.map
@jonnyradars
Ай бұрын
Вот ещё хорошее видео с размышлениями про дизайн систем типов в контексте функций в раст и плюсах, и каких проблем из C++ дизайн Rust избегает kzread.info/dash/bejne/haWIl7ugnLqZobg.html
Споткнулся на 1:05 "Вместо ??? нельзя написать Iterator, ведь Iterator это не тип" Но почему нельзя описать сигнатуру так fn map(self, f: F) -> I where F: FnMut(Self::Item) -> R, I: Iterator {}
@AndrewKozin
Жыл бұрын
Ага, нашёл в начале 7 лекции объяснение. Фактически, тут я замел проблему под ковёр, вернее перекинул её на сторону вызывающего кода, который должен специфицировать конкретный тип итератора, чего уже он сделать не сможет.
1:36:36 DoubleEndedIterator позволяет итерироваться с _обоих_ концов, а не с _обеих_ )
@alekseykladov1144
5 жыл бұрын
Спасибо, исправил!
На слайдах множество ошибок. Например попробуйте запустить код со слайда 36 ("Минимальный итератор"). Возможно автор сделал это специально следуя устаревшей традиции заставить поломать голову изучающим, но это только сильно ухудшает понимание материала. Т.к. не понятно это я неправильно понимаю основы языка, а код верный или наоборот. В сочетании с манерой ведущего говорить, воспринимать очень сложно.
Очень, очень сложно понимать о чем идет речь если нет С++ и/или Haskell опыта.
@stalexxx2
5 жыл бұрын
Зачем Вам тут haskell? И что вы предлагаете?
@vabka-7708
5 жыл бұрын
хз. Особо опыта кодинга на плюсах не было. Среду для хаскеля не смог поднять. Норм опыт только C# и F# - всё легко понимается. Ещё регулярно приходится залезать в js и ts, и после них Rust, как глоток свежего воздуха - наконец-то язык с нормальным дизайном и хорошим тулигом из коробки
@Pavel.Zhigulin
4 жыл бұрын
@@vabka-7708 По ходу Rust глоток свежего воздуха для всех :D Я думал только для С++ ребят, вроде меня)
@slvrization
4 жыл бұрын
Если есть опыт в Scala, то многие языковые конструкции будут очень знакомы. Но про кресты не помешает иметь общее представление, это да.
Прошу прощения, но вы так быстро говорите, что что-то понять, особенно новичкам, очень сложно:)
@luna_moonspeak
5 жыл бұрын
Вам доступна кнопка "пауза", рекомендую!
@justrobert5861
5 жыл бұрын
@@luna_moonspeak ваша рекомендация очень тупа. Из-за того, что я нажму на паузу, я больше пойму? Боже, если не знаете что говорить, то не комментируйте людей вовсе!
@jonwise3419
5 жыл бұрын
Честно говоря, люди тут правы, мне кажется. Это видео лекции, скорость контролирует слушатель, а не лектор (к счастью для всех, так как для каждого оптимальна разная скорость). Есть скорость произведения видео. Я например обычно на 1.25 - 1.5х смотрю и, когда что-то сложное или мозг не такой свежий, то ставлю меньше скорость. Но я лично заметил что лучше иногда что-то несколько раз прослушать что-то, нежели замедлять. Таким образом мозг уже обобщает многие вещи и при след. прослушивании все легче и легче. Я обычно поэтому книги и лекции лучше несколько раз быстро прослушаю нежели один раз но медленно.
@justrobert5861
5 жыл бұрын
@@jonwise3419 Спасибо за комментарий. Думаю, что тут каждому своё. Видимо, я ещё слишком мал для того, чтобы так воспринимать информацию.
Предлагаю скинуться ему репетитора по русскому языку :)
@norbertnemesh
2 жыл бұрын
По английскому тоже не помешал бы