Как уже отметил наш постоянный зритель несколько месяцев назад, токены Толкина действительно были пущены в оборот. Кто бы мог подумать пару лет назад... (отсылка к старым стримам по ERC20) https://www.reddit.com/media?url=https%3A%2F%2Fi.redd.it%2Fjust-arrived-in-the-mail-today-v0-fkqtrcac6wgc1.jpeg%3Fs%3D9df19cbd93dcc9ece791fb096a2e6d15e0a9d7ec
Reddit
https://i.redd.it/just-arrived-in-the-mail-today-v0-fkqtrcac6wgc1.jpeg?s=9df19cbd93dcc9ece791fb096a2e6d15e0a9d7ec
😁7👍1
Некоторые замечают, что при использовании Metamask в тестовой среде с Hardhat происходят какие-то дополнительные странные вызовы. В частности, если попытаться отправить обычную транзакцию, в журнале Hardhat может вылезти ещё штук пять сообщений вроде "unrecognized selector". Откуда это берётся?
Я провёл небольшое расследование, и дело в том, что Metamask пытается вызывать функции
Так что варианта два - просто игнорировать, либо добавить пустую функцию fallback (плюс добавить наследование от контракта ERC165). Ну, то есть можно сделать пустые функции decimals, symbol, но это как-то странно, если контракт не связан с токенами.
Я провёл небольшое расследование, и дело в том, что Metamask пытается вызывать функции
supportsInterface() (ERC165), а также функции типа decimals() и symbol(), тк совпадают селекторы, к примеру bytes4(keccak256(bytes("symbol()"))) вернёт 0x95d89b41, это как раз один из неопознанных селекторов. Любопытно, что это вызывается, даже если вы не используете ERC20.Так что варианта два - просто игнорировать, либо добавить пустую функцию fallback (плюс добавить наследование от контракта ERC165). Ну, то есть можно сделать пустые функции decimals, symbol, но это как-то странно, если контракт не связан с токенами.
🔥10👍1
В этом уроке по Solidity и Ethereum мы напишем для нашего контракта фронт-энд на Next.js и Typescript. Это обновлённый урок, в котором мы будем использовать все свежие зависимости и библиотеки. https://www.youtube.com/watch?v=PbAk097nM_Q
YouTube
Solidity и Ethereum, урок #69 | Фронт-энд на Next.js и Typescript (ОБНОВЛЕНИЕ 2024 года)
ХОТИТЕ СТАТЬ РАЗРАБОТЧИКОМ Solidity, узнать об Ethereum, блокчейне и многом другом ещё больше?!
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
❤11🔥5👍3👏1
И тут я вспоминаю об этом нашем кавере и хочется танцевать так, как будто никто не видит (тем более, что никто и не видит) https://soundcloud.com/ravens-die-laughing/zvezdy
SoundCloud
Zvezdy (Звёзды, Molchat Doma cover)
Ailura - vocals
Kruk - bass, mastering, production
Original author - Molchat Doma
Kruk - bass, mastering, production
Original author - Molchat Doma
👍9😱2😐2
По этой теме было много вопросов, так что во вторник проведём стрим.
Мы поговорим о новом весьма хайповом "стандарте" ERC404, который на самом деле и не стандарт вовсе. В любом случае, это подход позволяет создавать комбинацию токенов ERC20 и ERC721, вводя для NFT понятие "долей". Мы разберём, в чём польза этого подхода и как он работает.
https://youtube.com/live/7TZFpbge83A
Мы поговорим о новом весьма хайповом "стандарте" ERC404, который на самом деле и не стандарт вовсе. В любом случае, это подход позволяет создавать комбинацию токенов ERC20 и ERC721, вводя для NFT понятие "долей". Мы разберём, в чём польза этого подхода и как он работает.
https://youtube.com/live/7TZFpbge83A
YouTube
Solidity и Ethereum, урок #70 | ERC404: комбинация токенов ERC20/ERC721 | Стандарт, которого нет
ХОТИТЕ СТАТЬ РАЗРАБОТЧИКОМ Solidity, узнать об Ethereum, блокчейне и многом другом ещё больше?!
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 20% на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 20% на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
🔥7👍2❤1👏1
Что ж, цикл "Воспоминания" Тэффи завершён. К сожалению, завершился он на довольно грустной ноте, которая подозрительно похожа на происходящее сегодня, так что добавил ещё две бонусные главы. В ближайшие дни ещё будут "воспоминания" о таком известном человеке, как Григорий Распутин, а также об Алексее Толстом (это который "не Лев") https://youtu.be/GOx8e0-8Tws
YouTube
Надежда Тэффи: Воспоминания (в период Гражданской войны) | 27, 28, 29, 30, 31 главы + бонусные главы
Надежда Александровна Тэффи, "Воспоминания". Здесь представлены главы с двадцать седьмой по тридцать первую плюс две бонусные главы.
00:00 Глава 27
09:23 Глава 28
18:54 Глава 29
24:31 Глава 30
33:13 Глава 31
43:13 Первое посещение редакции
50:09 Псевдоним…
00:00 Глава 27
09:23 Глава 28
18:54 Глава 29
24:31 Глава 30
33:13 Глава 31
43:13 Первое посещение редакции
50:09 Псевдоним…
❤4👍3🆒2⚡1
Вышел Hardhat 2.20 с поддержкой предстоящего хард-форка Cancun (выходит в середине марта), который должен добавить быстродействия и безопасности. Также поддерживается Solc 0.8.24. https://github.com/NomicFoundation/hardhat/releases/tag/hardhat%402.20.0
GitHub
Release Hardhat v2.20.0 — Cancun · NomicFoundation/hardhat
This release adds support for the upcoming cancun hardfork. This hardfork is not enabled by default; if you want to use it, then you have to enable it in your Hardhat config:
module.exports = {
n...
module.exports = {
n...
👍7
Ребята из MIT выложили некоторые свои курсы в открытый доступ (но там, кажется, ограниченный срок записи). Вот, к примеру - https://www.edx.org/learn/computer-science/massachusetts-institute-of-technology-introduction-to-computer-science-and-programming-using-python Это самые основы, для тех, кому не хватает фундамента (кое-что из этого мы разбирали в плейлисте Алгоритмы)
edX
MITx: Introduction to Computer Science and Programming Using Python. | edX
An introduction to computer science as a tool to solve real-world analytical problems using Python 3.5.
🔥15
В этом уроке мы поговорим про паттерн Extension, который можно использовать, если ваш контракт слишком громоздкий и не вписывается в максимально допустимый размер Ethereum. Этот паттерн довольно простой, но позволяет эффективно решать данную проблему. https://www.youtube.com/watch?v=p-XgxfCB50I
YouTube
Solidity и Ethereum, урок #71 | Паттерн Extension: что делать, если контракт слишком большой?!
ХОТИТЕ СТАТЬ РАЗРАБОТЧИКОМ Solidity, узнать об Ethereum, блокчейне и многом другом ещё больше?!
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
🔥10🙏1
Недавно написал пост, в котором исследуется любопытный вопрос - как вытащить все страницы сайта для последующей обработки? Перечислены разные варианты, в том числе с помощью скрипта на Python https://www.scrapingbee.com/blog/how-to-find-all-urls-on-a-domains-website-multiple-methods/
Scrapingbee
How to find all URLs on a domain’s website (multiple methods) | ScrapingBee
Crawl any website! Step-by-step guide to finding all URLs on a domain to make scraping all their content easy. Multiple methods that are easy to follow.
👍8⚡1
Ещё одна подборка с разнообразными ресурсами по теме IT и программирования https://github.com/charlax/professional-programming
GitHub
GitHub - charlax/professional-programming: A collection of learning resources for curious software engineers
A collection of learning resources for curious software engineers - charlax/professional-programming
👍8
Последний наверное год-полтора мы периодически заходили в местную китайскую забегаловку с аутентичной едой и такой непринуждённой атмосферой лёгкой неприбранности. Моя жена сильно похожа на китаянку, так что мы в один момент как-то разговорились с владелицей заведения, и с тех пор каждый раз перетирали за жизнь. Конечно, на английском, хотя на базовом уровне она латышский тоже освоила. Да и я, сказать честно, не мастер в этом плане - хотя тут мне пеняют на то, что я и в русском ударению ставлю неправильно. Что поделать, мог бы вообще говорить с характерным акцентом.
Мне казалось, что имя Элайджа совсем простое, но нашей знакомой оно показалось каким-то сверх-сложным 😂 Помню ещё, я пытался провести аналогию с Элайджей Вудом - актёром из Властелина колец, но, оказывается, этот фильм совершенно неизвестен в Китае. Ну, я, как фанат Толкина, был уверен, что профессора знают по всему миру 🤓
Вообще, интересно подмечать, как всё-таки люди отличаются друг от друга, но всё равно могут найти общий язык. Поэтому, думается, стоит путешествовать, общаться с представителями разных культур. И поэтому, к сожалению, тоталитарные режимы пытаются оградить граждан от "тлетворного влияния". Потому что когда ты знакомишься с людьми "оттуда", ты понимаешь, что с ними вполне можно взаимодействовать...
К сожалению, с начала года, проходя мимо этого заведения, мы всё время видели за прилавком неизвестную девушку, кажется, местную. Раньше периодически "на хозяйстве" была дочка владельцев, но теперь и она куда-то исчезла. А на той неделе я с удивлением обнаружил, что на здании сменилась вывеска, и там теперь какие-то кебабы (kebabs, это шаурма). Искал в интернете какие-то сведения, ничего не нашёл. Странно, и жаль.
А тут ещё другие азиатские друзья - корейский ресторан - тоже переехал чёрт знает куда, только на велосипеде доедешь. Как-то всё разом 🤪
Это, конечно, в общем и целом пост наигранной весёлости, так как весёлого мало, но жаль, когда люди, с которыми ты, вроде, был в каком-то контакте, исчезают. https://www.youtube.com/watch?v=bsTxR64s5Kc
Мне казалось, что имя Элайджа совсем простое, но нашей знакомой оно показалось каким-то сверх-сложным 😂 Помню ещё, я пытался провести аналогию с Элайджей Вудом - актёром из Властелина колец, но, оказывается, этот фильм совершенно неизвестен в Китае. Ну, я, как фанат Толкина, был уверен, что профессора знают по всему миру 🤓
Вообще, интересно подмечать, как всё-таки люди отличаются друг от друга, но всё равно могут найти общий язык. Поэтому, думается, стоит путешествовать, общаться с представителями разных культур. И поэтому, к сожалению, тоталитарные режимы пытаются оградить граждан от "тлетворного влияния". Потому что когда ты знакомишься с людьми "оттуда", ты понимаешь, что с ними вполне можно взаимодействовать...
К сожалению, с начала года, проходя мимо этого заведения, мы всё время видели за прилавком неизвестную девушку, кажется, местную. Раньше периодически "на хозяйстве" была дочка владельцев, но теперь и она куда-то исчезла. А на той неделе я с удивлением обнаружил, что на здании сменилась вывеска, и там теперь какие-то кебабы (kebabs, это шаурма). Искал в интернете какие-то сведения, ничего не нашёл. Странно, и жаль.
А тут ещё другие азиатские друзья - корейский ресторан - тоже переехал чёрт знает куда, только на велосипеде доедешь. Как-то всё разом 🤪
Это, конечно, в общем и целом пост наигранной весёлости, так как весёлого мало, но жаль, когда люди, с которыми ты, вроде, был в каком-то контакте, исчезают. https://www.youtube.com/watch?v=bsTxR64s5Kc
YouTube
六翼天使 (Seraphim) - 日出東方 (Rising) (Full album HQ)
Ripped from FLAC. Mp4 - 512 Kbps, 44.1 kHz.
Band: 六翼天使 (Seraphim)
Genre: Melodic Power Death Metal
Album: 日出東方 (Rising)
Year: 2008
Country: Taiwan (Taipei)
Tracklist:
01 | 00:00 | 情欲反叛 (Betray)
02 | 06:43 | 無涯的希望 (Innocent Endless Hope)
03 | 12:43 | 永 (Permanence)…
Band: 六翼天使 (Seraphim)
Genre: Melodic Power Death Metal
Album: 日出東方 (Rising)
Year: 2008
Country: Taiwan (Taipei)
Tracklist:
01 | 00:00 | 情欲反叛 (Betray)
02 | 06:43 | 無涯的希望 (Innocent Endless Hope)
03 | 12:43 | 永 (Permanence)…
😢3👍2🌭1
В этом уроке мы поговорим о EIP2929 и EIP2930, о газе и его оптимизации. Мы узнаем, что такое холодное и горячее (hot/warm) обращение и почему это важно. Кроме того, мы узнаем, что такое accessList в транзакциях и как он может помочь заранее "разогреть слоты" для экономии газа. В конце мы используем этот подход в паттерне Extension. https://www.youtube.com/watch?v=RRXLzfUgcLE
YouTube
Solidity и Ethereum, урок #72 | EIP2929 и 2930: Холодный и горячий доступ, accessList, экономия газа
ХОТИТЕ СТАТЬ РАЗРАБОТЧИКОМ Solidity, узнать об Ethereum, блокчейне и многом другом ещё больше?!
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
🔥10⚡2👏1
Тут выложили нашу дискуссию про ERC404 безо всяких технических заумностей https://t.iss.one/izidaovoice/69
Telegram
Izi DAO Voice
Matapac X Ilya Krukowski
Раскайфовка по ERC-404
Чо за аппарат
00:00 ERC-721 и ERC-1155.
03:11 ERC-20.
06:40 ERC-404 в общих чертах.
09:10 Характерные особенности.
Как работает
13:10 Техническая реализация.
15:30 Обзор функции "transferFrom" и аргумента…
Раскайфовка по ERC-404
Чо за аппарат
00:00 ERC-721 и ERC-1155.
03:11 ERC-20.
06:40 ERC-404 в общих чертах.
09:10 Характерные особенности.
Как работает
13:10 Техническая реализация.
15:30 Обзор функции "transferFrom" и аргумента…
👍13
К вопросу об указателях, в том числе и умных, в Rust
Система владения и заимствования в Rust, а также наличие разнообразных указателей может сильно запутать поначалу, особенно когда выясняется, что указатели бывают умные, а бывают - не очень. Это не говоря о том, что у нас есть referencing, а есть ещё dereferencing, и всё это вместо нужно как-то увязать. Попробуем разобраться.
Есть вот такой код:
a будет иметь тип i32, эта переменная "знает", где лежит число 5. Так как это простой тип данных, то число лежит в стеке. Кроме того, помним, что a "владеет" этим числом и в нужный момент должна удалить соответствующие данные.
В случае с b мы используем оператор referencing
Однако никто не мешает нам сказать "дай мне то значение, которое лежит по этому указателю". Для этого используется оператор dereferencing, "звёздочка":
Теперь сравнение работает. Причём мы можем даже присвоить это значение другой переменной:
Но значит ли это, что изменение c приведёт к измению a и/или b? На самом деле, нет. Мы опять же работаем с простым типом данных, и присваивание приводит к тому, что значение копируется для другой переменной, то есть a и c имеют разные, независимые значения.
С типами вроде vec и string ситуация похожая, но становится несколько сложнее.
Мы создали вектор из трёх элементов, и мы знаем, что он будет хранится в heap, потому что потенциально его длина может меняться. В стек Rust может поместить только значения, размер которых точно известен во время компиляции, и вектор к такому типу (в отличие от фиксированного массива) не относится.
Но тогда вопрос: что же содержит в себе переменная a? Она по крайней мере должна знать, с какого адреса в heap начинается наш вектор и какой у него размер. То есть выходит, что это тоже какой-то указатель. Но "простой" указатель в духе &b данными не владеет, а просто ссылается на них. В нашем же случае мы явно ожидаем, что a владеет вектором, ведь кто-то же должен в итоге очистить память.
Ответ заключается в том, что vector (как и string) - это умный указатель, smart pointer, который действительно указывает на heap, но при этом владеет данными там и имеет пристыкованные метаданные.
Значит, если мы напишем
то мы фактически тоже создадим указатель, который в свою очередь будет ссылатьcя на "умный указатель", и это, как говорится, две большие разницы.
К подобным типам данных тоже можно попытаться применить dereferencing, но вот такая строка выдаст ошибку:
В отличие от простых типов данных, вектора и строки при присваивании не копируются, а переносятся. То есть к примеру вот такое
приведёт к тому, что вектор "перенесётся" в d, ну то есть на него теперь указывает другая переменная. Когда же мы делаем
Это сработает, но мы именно полностью копируем вектор, он будет независим от вектора a.
Но тут можно задать новый вопрос - раз a тоже является указателем, можем мы сможем сделать dereferencing для него? Можно попробовать:
Тип b определится как [i32], но программа не скомпилируется. Фактически мы пытается влезть напрямую в данные, на которые указывает умный указатель, и это получается просто массив. Массивы в Rust фиксированные и лежат в стеке, но Rust не может сунуть этот конкретный массив в стек, потому что неизвестна его длина в текущий момент времени!
Если вы думаете, что это всё, то ничуть не бывало. Есть ещё метод, который называется
Система владения и заимствования в Rust, а также наличие разнообразных указателей может сильно запутать поначалу, особенно когда выясняется, что указатели бывают умные, а бывают - не очень. Это не говоря о том, что у нас есть referencing, а есть ещё dereferencing, и всё это вместо нужно как-то увязать. Попробуем разобраться.
Есть вот такой код:
let a = 5;
let b = &a;
a будет иметь тип i32, эта переменная "знает", где лежит число 5. Так как это простой тип данных, то число лежит в стеке. Кроме того, помним, что a "владеет" этим числом и в нужный момент должна удалить соответствующие данные.
В случае с b мы используем оператор referencing
&, то есть фактически делаем указатель. Тип b будет &i32, эта переменная знает, у кого спросить, где находится нужное число (знает это а). При этом b не получает владение этим числом. Больше того, мы не можем даже сравнить а и b напрямую, код a == b; вернёт ошибку - типы разные, мы не можем сравнить само число i32 и указатель на него.Однако никто не мешает нам сказать "дай мне то значение, которое лежит по этому указателю". Для этого используется оператор dereferencing, "звёздочка":
a == *b;
Теперь сравнение работает. Причём мы можем даже присвоить это значение другой переменной:
let mut c = *b;
c = c + 1;
Но значит ли это, что изменение c приведёт к измению a и/или b? На самом деле, нет. Мы опять же работаем с простым типом данных, и присваивание приводит к тому, что значение копируется для другой переменной, то есть a и c имеют разные, независимые значения.
С типами вроде vec и string ситуация похожая, но становится несколько сложнее.
let a = vec![1, 2, 3];
Мы создали вектор из трёх элементов, и мы знаем, что он будет хранится в heap, потому что потенциально его длина может меняться. В стек Rust может поместить только значения, размер которых точно известен во время компиляции, и вектор к такому типу (в отличие от фиксированного массива) не относится.
Но тогда вопрос: что же содержит в себе переменная a? Она по крайней мере должна знать, с какого адреса в heap начинается наш вектор и какой у него размер. То есть выходит, что это тоже какой-то указатель. Но "простой" указатель в духе &b данными не владеет, а просто ссылается на них. В нашем же случае мы явно ожидаем, что a владеет вектором, ведь кто-то же должен в итоге очистить память.
Ответ заключается в том, что vector (как и string) - это умный указатель, smart pointer, который действительно указывает на heap, но при этом владеет данными там и имеет пристыкованные метаданные.
Значит, если мы напишем
let b = &a;
то мы фактически тоже создадим указатель, который в свою очередь будет ссылатьcя на "умный указатель", и это, как говорится, две большие разницы.
К подобным типам данных тоже можно попытаться применить dereferencing, но вот такая строка выдаст ошибку:
let c = *b;
В отличие от простых типов данных, вектора и строки при присваивании не копируются, а переносятся. То есть к примеру вот такое
let a = vec![1, 2, 3];
let d = a;
приведёт к тому, что вектор "перенесётся" в d, ну то есть на него теперь указывает другая переменная. Когда же мы делаем
let c = *b;, то мы фактически пытаемся через b влезть в данные a и сделать перемещение. Компилятору такой манёвр не сильно нравится, а скопировать весь вектор автоматом тоже не выходит, такую команду мы должны отдать сами:let c = (*b).clone();
Это сработает, но мы именно полностью копируем вектор, он будет независим от вектора a.
Но тут можно задать новый вопрос - раз a тоже является указателем, можем мы сможем сделать dereferencing для него? Можно попробовать:
let b = *a;
Тип b определится как [i32], но программа не скомпилируется. Фактически мы пытается влезть напрямую в данные, на которые указывает умный указатель, и это получается просто массив. Массивы в Rust фиксированные и лежат в стеке, но Rust не может сунуть этот конкретный массив в стек, потому что неизвестна его длина в текущий момент времени!
Если вы думаете, что это всё, то ничуть не бывало. Есть ещё метод, который называется
.deref():👍6
let a = String::from("test");
let b = a.deref();Тип b будет &str (если бы там был вектор, тип бы стал &[i32]). Чувствуете разницу? Этот метод сделает указатель непосредственно на данные, но он не попытается эти данные куда-то перенести. Если же перед deref поставить звёздочку, то мы опять получим ошибку:
*(a.deref()), потому что опять будет сделана попытка вытащить сами данные из heap и куда-то их перетащить. Фактически, здесь *(a.deref()) равносильно *a.При этом для простых типов
deref не имеет смысла. На типах вроде i32 его нет вовсе, на указателях это метод просто вернёт сам указатель:let a: i32 = 5;
let b = &a;
let c = b.deref();
Тип c будет &i32, как у b.
Интересно, что в ряде случаев Rust умеет делать dereference автоматически для нашего же удобства. К примеру, есть функция:
fn call(s: &str) {
println!("{}", s);
}Она может принять как &str, так и String:
let a = "test";
let b = String::from(a);
call(a);
call(&b);
Работает это потому, что у String есть trait Deref (про него будет в видео), который умеет делать dereferencing в обычный &str.
То есть функция делает что-то такое:
let borrowed = &b;
let my_str = c.deref();
Тип my_str будет &str, то есть ровно то, что написано в функции. Хотя мы могли бы сделать слайс &str сами, это уж очень неудобно, ведь нужно получить сами данные из умного указателя, сделать заимствование, и потом создать слайс:
let borrowed = &b;
let my_str = &(*borrowed)[..];
А так deref() вызовется для нас, причём столько раз, сколько требуется, поэтому если функция принимает массив вида
&[i32], то туда можно запихнуть и вектор с числами того же типа.Теперь мы понимаем, какие есть указатели и как из них получать данные. Интересно, что мы можем создавать и свои умные указатели в Rust, и самым простым является
Box - он положит наши данные в heap и сделает привязку к ним по аналогии с тем, что делает vector или string:let a: Box<i32> = Box::new(42);
То есть наши число теперь торчит не в стеке, а в heap, и a содержит в себе умный указатель. Это значит, что мы можем тоже делать referencing и dereferencing:
let a: Box<i32> = Box::new(42);
let b: &Box<i32> = &a;
let c: &i32 = a.deref();
let d: i32 = *a;
Из аннотации типов можно легко видеть, где что получается. Кстати,
*a тут тоже работает в отличие от истории с векторами и строками, потому что размер целого числа точно известен, его можно скопировать и поместить в стек. То есть в d будет число, независимое от того, на которое указывает a (там вообще выходит, что он сначала делает deref, потом звёздочку).Однако вот так всё равно сделать нельзя:
let e = *b;, как и в предыдущих примерах. *b укажет на сам Box<i32>, копировать его автоматом Rust не будет, так что там придётся написать clone()Но тут вопрос: зачем нам вообще этот box нужен, если лучше хранить простые типы в стеке, который банально быстрее работает? Это так и есть, во многих случаях хранить обычное число "в коробке" смысла нет. Но если у нас есть данные, размер которых заранее неизвестен, то это может быть очень актуально.
К примеру, есть вот такая структура, описывающая кошку:
struct Cat {
name: String,
age: u8,
}
let cat = Cat {
name: String::from("Mr. Buttons"),
age: 3,
};Где будет хранится наш Mr. Buttons? Сама структура будет в стеке, но строка как таковая будет в heap (в стеке же будет указатель на неё).
Однако предположим, что у кошки может быть предок, и это тоже кошка:
struct Cat {
name: String,
age: u8,
parent: Option<Cat>,
}Можно ли такую структуру запихнуть в стек? Нет, потому что она рекурсивная, и её размер во время компиляции определить невозможно. Дело в том, что у Mr. Buttons может быть потомок, у того свой потомок, и так до бесконечности. Поэтому родителя нужно хранить в heap, и это тот случай, когда нам нужен Box:
struct Cat {
name: String,
age: u8,
parent: Option<Box<Cat>>,
}Создадим двух кошек:
👍5
let cat_parent = Box::new(Cat {
name: String::from("Parent Cat"),
age: 3,
parent: None,
});
let cat = Cat {
name: String::from("Mr. Buttons"),
age: 3,
parent: Some(cat_parent),
};Можно сделать так, можно было первую кошку сделать без Box, и добавить Box::new только для parent у Mr Buttons.
Но с таким подходом есть проблема: cat_parent будет недоступен после создания Mr Buttons, тк там происходит move (перемещение). Вместо этого можно сделать clone:
parent: Some(cat_parent.clone()),. Это, правда, может быть не сильно оптимально, так как мы копируем всю структуру сразу, плюс фактически родитель для Mr Buttons и Parent Cat не связаны между собой (изменение возраста Parent Cat не приведёт к изменению возраста родителя).Можно попробовать добавить заимствование для родителя, но тогда придётся прописывать lifetimes. Если же мы хотим, чтобы родитель был связан с существующей кошкой, плюс к тому, изменения кошки приводило бы к изменению родителя, то нам потребуется использовать другие умные указатели. Их мы рассмотрим в следующем уроке.
👍5🔥3❤1🤯1