Repository: chriskrycho/newrustacean.com Branch: main Commit: 0838780a8747 Files: 233 Total size: 2.0 MB Directory structure: gitextract_cw5hn_qg/ ├── .editorconfig ├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE.md ├── Makefile ├── README.md ├── build.rs ├── docs/ │ ├── bonus/ │ │ ├── 10-script.md │ │ ├── 13-silly-mistakes.md │ │ ├── 14-my-workflow.md │ │ ├── burnout-script.md │ │ └── translating-between-languages-script.md │ ├── bonus-2-script.md │ ├── bonus-3-script.md │ ├── bonus-4-script.md │ ├── bonus-5-script.md │ ├── bonus-6-script.md │ ├── bonus-7-script.md │ ├── bonus-8-script.md │ ├── bonus-9-script.md │ ├── cysk/ │ │ ├── bindgen-cbindgen-script.md │ │ ├── serde.md │ │ └── wasm.md │ ├── cysk-1.md │ ├── cysk-2.md │ ├── cysk-3.md │ ├── cysk-rayon.md │ ├── cysk-rocket.md │ ├── e000-script.md │ ├── e001-script.md │ ├── e002-script.md │ ├── e003-script.md │ ├── e004-script.md │ ├── e005-script.md │ ├── e006-script.md │ ├── e007-script.md │ ├── e008-script.md │ ├── e009-script.md │ ├── e010-script.md │ ├── e011-script.md │ ├── e011-transcript.md │ ├── e012-script.md │ ├── e014-script.md │ ├── e015-script.md │ ├── e016-script.md │ ├── e017-script.md │ ├── e018-script.md │ ├── e019-script.md │ ├── e020-script.md │ ├── e021-script.md │ ├── e022-script.md │ ├── e023-script.md │ ├── e024-script.md │ ├── e025-script.md │ ├── e026-script.md │ ├── e027-script.md │ ├── e028-script.md │ ├── e029-script.md │ ├── e030-script.md │ ├── e031-script.md │ ├── interview/ │ │ └── diesel-1.0/ │ │ ├── master.md │ │ ├── part-1.md │ │ └── part-2.md │ ├── interview-1-part-1-script.md │ ├── interview-1-part-2-script.md │ ├── interview-3-script.md │ ├── interview-4-part-1.md │ ├── interview-4-part-2.md │ ├── interview-4-part-3.md │ ├── interview-4-sponsors.md │ ├── irr_2017/ │ │ ├── anna-liao.md │ │ ├── lee-baillie.md │ │ └── matt-gathu.md │ ├── meta-2.md │ ├── meta-3.md │ ├── news/ │ │ ├── 1-script.md │ │ ├── 2-script.md │ │ ├── increasing-rusts-reach.md │ │ ├── rust-1-20.md │ │ ├── rust-1-21-1-22.md │ │ ├── rust-1-23.md │ │ ├── rust-1-24.md │ │ ├── rust-1-25.md │ │ ├── rust-1-26.md │ │ ├── rust-1-27.md │ │ ├── rust-1-28.md │ │ ├── rust-1-31/ │ │ │ ├── part-1.md │ │ │ └── part-2.md │ │ ├── rust-1-32.md │ │ ├── rust-1.33-and-1.34.md │ │ ├── rust-1.35.md │ │ └── rust_1_29_1_30.md │ └── rbr_2017/ │ ├── andrew-hobden.md │ ├── anthony-deschamps.md │ ├── arun-kulshreshtha.md │ ├── ben-striegel.md │ ├── colin-dean.md │ ├── holden-marcsisin.md │ ├── jess-saxeter.md │ ├── master-script.md │ └── pete-lyons.md ├── landing/ │ ├── index.html │ ├── landing.css │ └── sponsors.html ├── resources/ │ ├── .nojekyll │ ├── CNAME │ ├── favicon.pxm │ ├── feed.xml │ ├── media-playback.css │ └── media-playback.js ├── rust-toolchain.toml └── src/ ├── bonus/ │ ├── _1.rs │ ├── _10.rs │ ├── _13.rs │ ├── _14.rs │ ├── _2.rs │ ├── _3.rs │ ├── _4.rs │ ├── _5.rs │ ├── _6.rs │ ├── _7.rs │ ├── _8.rs │ ├── _9.rs │ ├── burnout.rs │ ├── mod.rs │ └── translating_between_languages.rs ├── cysk/ │ ├── _1.rs │ ├── _2.rs │ ├── _3.rs │ ├── bindgen_cbindgen.rs │ ├── mod.rs │ ├── rayon.rs │ ├── rocket.rs │ ├── serde.rs │ └── wasm.rs ├── e000.rs ├── e001.rs ├── e002.rs ├── e003.rs ├── e004.rs ├── e005.rs ├── e006.rs ├── e007.rs ├── e008.rs ├── e009.rs ├── e010.rs ├── e011.rs ├── e012.rs ├── e013.rs ├── e014.rs ├── e015.rs ├── e016.rs ├── e017.rs ├── e018.rs ├── e019.rs ├── e020.rs ├── e021.rs ├── e022.rs ├── e023.rs ├── e024.rs ├── e025.rs ├── e026.rs ├── e027.rs ├── e028.rs ├── e029/ │ ├── ffi-demo.c │ ├── ffi-demo.h │ └── mod.rs ├── e030.rs ├── e031/ │ ├── e031.c │ ├── e031.h │ └── mod.rs ├── includes/ │ └── media-playback-speed.html ├── interview/ │ ├── _1/ │ │ ├── mod.rs │ │ ├── part_1.rs │ │ └── part_2.rs │ ├── _2/ │ │ ├── mod.rs │ │ ├── part_1.rs │ │ └── part_2.rs │ ├── _3.rs │ ├── _4/ │ │ ├── mod.rs │ │ ├── part_1.rs │ │ ├── part_2.rs │ │ └── part_3.rs │ ├── diesel_1_0/ │ │ ├── mod.rs │ │ ├── part_1.rs │ │ └── part_2.rs │ ├── integer32.rs │ ├── irr_2017/ │ │ ├── anna_liao.rs │ │ ├── lee_baillie.rs │ │ ├── matt_gathu.rs │ │ └── mod.rs │ ├── mod.rs │ └── rbr_2017/ │ ├── andrew_hobden.rs │ ├── anthony_deschamps.rs │ ├── arun_kulshreshthra.rs │ ├── ben_beckwith.rs │ ├── ben_striegel.rs │ ├── colin_dean.rs │ ├── esty_thomas.rs │ ├── holden_marcsisin.rs │ ├── jess_saxeter.rs │ ├── katie_nolan.rs │ ├── matthias_endler.rs │ ├── mod.rs │ ├── parry_wilcox.rs │ ├── pete_lyons.rs │ ├── thomas_gideon.rs │ └── tom_kriezkowski.rs ├── lib.rs ├── meta/ │ ├── _1.rs │ ├── _2.rs │ ├── _3.rs │ └── mod.rs └── news/ ├── _1.rs ├── _2.rs ├── _3.rs ├── mod.rs ├── rust_1_20.rs ├── rust_1_21_1_22.rs ├── rust_1_23.rs ├── rust_1_24.rs ├── rust_1_25.rs ├── rust_1_26.rs ├── rust_1_27.rs ├── rust_1_28.rs ├── rust_1_29_1_30.rs ├── rust_1_31/ │ ├── mod.rs │ ├── part_1.rs │ └── part_2.rs ├── rust_1_32.rs ├── rust_1_33_1_34.rs └── rust_1_35.rs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true indent_size = 4 [*.{js,html}] indent_size = 2 ================================================ FILE: .gitignore ================================================ # Rust/Cargo bits target Cargo.lock rls # Website bits *.mp3 *.m4a *.logicx recordings # Miscellaneous tooling bits .python-version .ruby-version # IDE .idea .sublime-* *.iml .vscode # Writing tools .Ulysses-* # Vim nonsense *.swp # Build output link-against-Rust ================================================ FILE: .travis.yml ================================================ language: rust cache: cargo rust: - nightly branches: only: - master script: - make all ================================================ FILE: Cargo.toml ================================================ [package] edition = "2018" name = "show-notes" # Version will match released show number! Episode 12 will be `0.1.2`. version = "0.3.1" authors = ["Chris Krycho "] [dependencies] regex = "0.2" libc = "0.2.54" [build-dependencies] cc = "1.0" [lib] crate-type = ["cdylib"] ================================================ FILE: LICENSE.md ================================================ License ======= Technical materials ------------------- The MIT License (MIT) Copyright (c) 2015 Chris Krycho Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Content ------- ### Human-friendly You can do basically whatever you want with the content (the podcast audio included). Remix to your heart's content. Mash it up, quote it, make a podcast-jam if you like. The only restriction we have on the use of our content is that you cite it---that's just being a good neighbor. The name and logo? Feel free to riff on them. You just can't claim the work as your own. The design of the logo belongs to my friend [Cameron Morgan][cam]. He's great. If you steal his stuff, I may have to sic the friendly Rust community on you. The legalese below just outlines this policy in lawyer-friendly terms. [cam]: //www.krop.com/spidercam/ ### Lawyer-friendly #### Creative Commons -- Attribution 4.0 International -- CC BY 4.0 ##### Section 1 – Definitions. 1. **Adapted Material** means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. 2. **Adapter's License** means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. 3. **Copyright and Similar Rights** means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section [2(b)(1)-(2)][4] are not Copyright and Similar Rights. 4. **Effective Technological Measures** means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. 5. **Exceptions and Limitations** means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. 6. **Licensed Material** means the artistic or literary work, database, or other material to which the Licensor applied this Public License. 7. **Licensed Rights** means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. 8. **Licensor** means the individual(s) or entity(ies) granting rights under this Public License. 9. **Share** means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. 10. **Sui Generis Database Rights** means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. 11. **You** means the individual or entity exercising the Licensed Rights under this Public License. **Your** has a corresponding meaning. ##### Section 2 – Scope. 1. **License grant**. 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non- exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: 1. reproduce and Share the Licensed Material, in whole or in part; and 2. produce, reproduce, and Share Adapted Material. 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 3. Term. The term of this Public License is specified in Section 6(a). 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. 5. Downstream recipients. 1. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. 2. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). 2. **Other rights**. 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 2. Patent and trademark rights are not licensed under this Public License. 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. ##### Section 3 – License Conditions. Your exercise of the Licensed Rights is expressly made subject to the following conditions. 1. **Attribution**. 1. If You Share the Licensed Material (including in modified form), You must: 1. retain the following if it is supplied by the Licensor with the Licensed Material: 1. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); 2. a copyright notice; 3. a notice that refers to this Public License; 4. a notice that refers to the disclaimer of warranties; 5. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 2. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and 3. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. ##### Section 4 – Sui Generis Database Rights. Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: 1. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; 2. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and 3. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. ##### Section 5 – Disclaimer of Warranties and Limitation of Liability. 1. **Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.** 2. **To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.** 3. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. ##### Section 6 – Term and Termination. 1. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. 2. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 2. upon express reinstatement by the Licensor. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. 3. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. 4. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. ##### Section 7 – Other Terms and Conditions. 1. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. 2. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. ##### Section 8 – Interpretation. 1. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. 2. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. 3. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. 4. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at [creativecommons.org/policies][policies], Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. Creative Commons may be contacted at [creativecommons.org][cc]. [policies]: //creativecommons.org/policies [cc]: //creativecommons.org ================================================ FILE: Makefile ================================================ # -- Define variables. -- # BUILD_DIR = target/doc SRC = src/*.rs LANDING = landing/*.html landing/*.css RESOURCES = resources/* resources/.nojekyll # -- Define build rules -- # .PHONY: all clean test docs publish default: all clean: rm -rf $(BUILD_DIR) # Generate everything, but just leave it in the build directory. all: test docs landing resources test: cargo test docs: env RUSTDOCFLAGS="--html-after-content src/includes/media-playback-speed.html" cargo doc --no-deps --document-private-items # Fancy landing page components. landing: $(LANDING) target_dir cp $(LANDING) target/doc # GitHub pages settings, favicon, RSS feed, etc. Note: the RSS feed is updated # manually, so running `make modules` won't update it. resources: $(RESOURCES) target_dir cp $(RESOURCES) target/doc target_dir: mkdir -p $(BUILD_DIR) ================================================ FILE: README.md ================================================ # New Rustacean This is a *slightly ridiculous* approach to building a podcast hosting setup using Rust's documentation tools, for the [New Rustacean] podcast. I'm making the site source publicly available so that others can follow along and learn from my successes, failures, and various misadventures along the way. Feel free to submit pull requests if you find typos or the like! [New Rustacean]: https://newrustacean.com I hope to evolve the structure here based on what will hopefully *become* the structure for sites generated with `cargo doc` in the future, with supplementary/guide-like material living in the `src/doc` directory. For an example of existing repositories which use this structure, see [rust-lang/rust] and [rust-lang/cargo]. [rust-lang/rust]: https://github.com/rust-lang/rust [rust-lang/cargo]: https://github.com/rust-lang/cargo ================================================ FILE: build.rs ================================================ use std::process::Command; use cc::Build; fn main() { // Build a C file to link into Rust code. Build::new().file("src/e029/ffi-demo.c").compile("ffi-demo"); // Build a C file which links *against* Rust code. Command::new("clang") .args([ "src/e031/e031.c", "-Ltarget/debug", "-lshow_notes", "-o", "link-against-rust", ]) .spawn() .expect("executed the build for linking in Rust from C"); } ================================================ FILE: docs/bonus/10-script.md ================================================ # Becoming a Contributor ## Chris Krycho ### Rust Belt Rust, 2017 --- ![family](http://cdn.chriskrycho.com/images/talks/rbr_2017/family.jpg) Note: Hello, everyone! It's good to see all of you. We only have half an hour, and even if that's ten to fifteen minutes longer than a normal New Rustacean episode, that's still not much time, so let's jump right in! Our theme is "Becoming a Contributor." There are two prongs to this talk, two big ideas I hope you all walk away with. --- ### Introduction: The Big Ideas Note: The first thing I hope all of you take away is that **there is no reason _you_ cannot contribute meaningfully** to the success of Rust – or indeed any open-source project you care about. Anyone can be a contributor. And not "even you" but perhaps "_especially_ you". The fact that you're an outsider, or new to programming, or new to systems programming: sometimes that makes you a _better_ contributor. Because you don't necessarily share the biases of – you're not wearing the same blinders that – someone who's been writing systems-level code for 20 years have. So the first idea: **you can contribute**. The second idea I hope you take away is **just *how many* ways there are to contribute meaningfully**. It has almost become a cliche in the Rust community to say "code isn't the only thing that matters," but I want to show you today just how true that is. And I want to make that point again more forcefully, because for all that we often say that, the idea that _shipping code_ is what really matters is the kind of pernicious lie that can come back and bite any of us. It certainly gets to me at times! But it's a lie, and we're going to see that in detail. That's the second big idea: **there are an _astounding_ number of ways you can contribute**. --- ### Introduction: Why? Honestly, some of both – but serving people most of all. Note: There are a lot of things to be passionate about in the world of software development. But at the end of the day, I care about software because I care about _people_. To borrow a label from Scott Wlaschin – a developer I admire enormously, mostly working over in the F# community – I am a _humanist_, not a _technologist_. The technologies are interesting in themselves to a degree; but I mostly care about the ways that technologies can help us serve people more effectively. As software developers, that takes a lot of shapes. But today I want to zoom in on just these two ideas about open-source software: --- ### Introduction: The Big Ideas Note: So: why these two ideas? For one thing, because I think they are among the most applicable to everyone here. We have an enormous open-source focus. But for another, because they can also serve as windows into the ways we can – and should – think about software more generally. So: let's talk about how you become a _contributor_. --- ### Introduction: Outline 1. Introduction 2. Why bother contributing? 3. Who is a contributor? 4. What is a contribution? How can you contribute? * ...so many things they won't fit on this slide. 5. When and where to contribute? 6. Conclusion Note: We're going to take this on in the good old grammar-school fashion: _who_, _what_, _when_, _where_, _why_, and _how_. We're not going to take them in that order though, and we might smash a few of them together. --- ## Why bother contributing? There is more work to be done than hands to do it. Always. Note: The first question we might be asking is: _why contribute at all_? Why should you be interested in becoming a contributor? And the best answer I can offer is: because there is more work than hands to do it. Always. Every open-source maintainer can tell you the truth of this. --- ## Who is a contributor? Note: People define this differently, but I have a very simple definition: **A contributor is _anyone_ who improves a project.** --- ### Who is a contributor? Examples For example: * submit a patch to fix a typo * add a small correction for a code sample in a project * file an issue instead of just suffering through a problem in silence * everything else we're going to talk about today --- ### Who is a contributor? Me! How I got here: ![my first Rust commit](http://cdn.chriskrycho.com/images/talks/rbr_2017/first-commit.png) Note: That might sound overblown, but it's really not. I am literally standing on this stage in front of you today because I submitted some small typo and code sample improvements to "Rust by Example" a few years ago, and realized: I can make a difference in this community. And that gave me the motivation I needed to _keep_ contributing. --- ### Who is a contributor? _All of us!_ We're meant to help each other. Note: I don't imagine the story is all that different for _most_ people who are open-source contributors in this room. Something got them over the hump, and it was probably something small, insignificant-seeming at the time. They might be particularly skilled in this thing or that thing, but in fact a lot of them are in those roles just because they saw a need and stepped up to fill it. And then kept at it for a long time. But it made them a contributor. And that feeling – of helping build something bigger than you can build on your own – is a good one. I'd go so far as to say it's part of what humans are _meant_ for. It's part of us in a deep, deep way. --- ## Who is a contributor? That's it. Really! No quibbling! And no magic! Note: If you're inclined to quibble with that definition, I challenge you to ask _why?_ I think, most often, it's because we feel defensive about wanting to project our own particular kinds of contribution as the most important, or the most valuable. But I'm more of the mindset that, as I read recently, "anyone who would be first… must be last of all, and servant of all." We should stop worrying about our own prestige and turf-marking, and start rejoicing in the many different ways people are able to make our projects better. There's no magic that makes you qualified to be a contributor. There's just a willingness to serve where you see a need. --- ## What & how can you contribute? (This is a very, _very_ long list.) Note: And that takes us into the "what" of all of this, the _how_. (Yes, I'm combining those two). **_What_ is a contribution? _How_ can you contribute?** Turns out, this is a _long_ list. --- ### What & how: code The obvious one. 😏 Fix bugs! Implement features! etc. ![good first issue](http://cdn.chriskrycho.com/images/talks/rbr_2017/good-first-issue.png) ![mentored](http://cdn.chriskrycho.com/images/talks/rbr_2017/mentored.png) ![easy](http://cdn.chriskrycho.com/images/talks/rbr_2017/easy.png) These are all over the ecosystem. Note: Let's get this right out of the way up front, because it's the most obvious: you can write code. You can fix bugs or help implement new features. You can do that even if you're not an expert – especially in the Rust community. Many Rust projects have gone out of their way to mark issues as good-first-issues, or easy-to-tackle, or mentorship-available. Maybe it's your first contribution to an open-source project: that's okay. You can take a stab at it, and the fact that it might not be good _is okay_. The whole point of these kinds of issues is that they give you a place where you can jump in safely. That goes equally for everything from the Rust compiler itself to many of the other projects in the ecosystem. Look at the repository, for example! And it's not just this project. _Lots_ of projects in the Rust ecosystem are like this. --- #### What & how: code – we're kind here No one will ever swear at you or insult for making a mistake in Rust-land. _Everyone_ makes mistakes. Remember: we want people to contribute! ![good first issue](http://cdn.chriskrycho.com/images/talks/rbr_2017/good-first-issue.png) ![mentored](http://cdn.chriskrycho.com/images/talks/rbr_2017/mentored.png) ![easy](http://cdn.chriskrycho.com/images/talks/rbr_2017/easy.png) Note: And no one is going to swear at you or insult for making a mistake here. Not even if you're working on something important, and not even if you've been doing it for a while. That is not. how. we. roll. here. Instead, we _want_ people to show up, knowing nothing: we're happy to help. So: try opening a PR and let people help you learn how to do it well! In fact, : if you haven't ever opened a PR on a Rust project, find one that looks interesting to you and has an issue tagged that way, and submit a PR before the weekend is out! You can do it! --- #### What & how: code – a caveat Code is not the only contribution. It's not even the most important contribution. It's just the most obvious contribution. Note: But code is not the only thing that makes you a contributor. I put it up front because I think it's worth doing – but I also wanted to get it out of the way. In every software community, it's easy to _over_-value the code. That might sound crazy, given that it's open-source _software_, but the reality is that no one fails to value the code. We _do_ often fail to value all the other things that make an open-source software project actually useful. It's certainly true that there's no project without the code. But it's also the case that there's no _useful_ software without a lot of other things besides the code, and we often undervalue those. --- ### Filing bugs ![filing bugs](http://cdn.chriskrycho.com/images/talks/rbr_2017/new-issue.png) Note: So let's take one step away from code, and talk about what is probably the single _easiest_ way anyone can contribute. _File issues._ If you're using a binary and it doesn't work, open a ticket. If you're integrating a library and it seems like the API doesn't do what it should, or if it seems like it's missing some functionality… well, you can suffer in silence, or you can open a bug ticket! Many times, the author of the software _doesn't know there's a problem_. The only way they can fix it is if they know about it! --- ### Docs You're probably on board with this already. Because undocumented and badly documented projects are really, _really_ frustrating! Note: Perhaps the thing most of you will be most persuaded of the utility of is _documentation_. All of us have faced the difficulty of trying to figure out how to integrate some poorly-documented (or undocumented!) library into our own codebase. That experience, in word, _sucks_. So working on documentation is one of the highest-value areas you can contribute to any project. It's also really hard, in a bunch of ways – harder, in some ways, than writing the code is! --- #### Docs: who? Explanation of how things work under the hood ≠ introductory documentation/API docs/learning materials/etc. Note: One kind of documentation is **explanation of how things work under the hood**. The implementer is the most qualified there! That doesn't mean they don't still need help even with that, though! Some people are incredible implementors and terrible explainers; you can often do a great service by serving as an "interpreter" for them – taking their explanations and making the literary tweaks and cleanups and polish that they need. Another kind of documentation, though, developers and maintainers are often really poorly equipped to write, and that's **introductory documentation**. This is the problem of expertise: when you know exactly how something is _meant_ to work, and especially when you're the one who implemented it, there are things that seem obvious to you which simply aren't obvious to someone approaching it for the first time. And as hard as you try, you _can't_ escape that entirely. You can imagine what it might be like not to know something, but there's no substitute for actually not knowing something. --- #### Docs – how? You, too, can document things in just 3 easy steps! 1. Write down the things you don't understand from the docs as you go. 2. When you figure them out, write that down, too. 3. Then: file an issue or write a PR to improve it! Note: What that means is that one of the most valuable things you can do as you learn a new library is _write down the things you don't understand from the docs as you go_. And when you figure them out, _write that down, too_. If nothing else, writing up that experience – filing it as an issue on the bug tracker, or otherwise getting it in the hands of the maintainers – can help them make important changes to things like the order various concepts are introduced, or adding little notes to help people feel comfortable with not knowing something until it _can_ be introduced later, and other things like that. It can help them recognize and fill in gaps in their docs – things they simply assumed but which they didn't realize they were assuming – and fill those in. At the most extreme, you might even help them realize that some parts of the docs need full rewrites… and the work you've done in writing things down might just be the foundation or the actual content of those new docs. --- #### Docs: varieties So what kinds of things would we call _documentation_? * API documentation * READMEs * Tutorials * Books * The Rust Reference Note: * Overview/talk through * Zoom on _Books_: Okay, books are a _huge_ undertaking, but they can genuinely serve as documentation. Especially for large projects. In fact, several of the most important pieces of "documentation" the Rust project itself has are books: "The Rust Programming Language", "Rust by Example", and "The Rustonomicon". But there are also important but totally unofficial books like Daniel Keep's "A Practical Intro to Macros in Rust 1.0" and "The Little Book of Rust Macros", or Jorge Aparicio's book on microcontrollers with Rust. * The Rust Reference: This is a special category, and one that's especially important to me. The Rust Reference is supposed to be an exhaustive guide to the language, and the value of that being complete and accurate is hard to overstate. It's also wildly out of date today. I wrote an RFC last year that said, basically, "We need to actually document everything! That includes updating the Reference!" The trick is: it's a huge undertaking, and while I and a few others made a good start on it earlier this year, that effort got bogged down by life, and it needs to be resuscitated. And it's not just Rust which could use investment in that area. Other languages and frameworks have the same issue. It's _really_ important that there be an answer other than "dive into the source and try to figure out what its intent is" – the more central the component is in the ecosystem, the more important that is. --- #### Docs: Translation ![translation](http://cdn.chriskrycho.com/images/talks/rbr_2017/translation.png) Note: Another huge place you can contribute to documentation is _translation_. For good or ill, English has become the sort of _primary_ language of programming, but that doesn't mean we should treat it as the _only_ language, or as _more important_ than other languages. Translating documentation is amazing and very needed work, and it's work that not everyone is really capable of! I'm fluent in English and… ancient Hebrew and ancient Greek. For some reason, there's not much demand for technical writing in Greek from the era when Plato was alive. So I'm not much use at translation. But many of you out there _are_ multilingual, and could take docs written in English and convert them for, say, Czech-speaking developers. Perhaps just as importantly, you can go the _other_ direction, and help non-English-speaking maintainers reach a broader audience. Take an amazing project which only has documentation in Amharic (because its developers don't feel comfortable enough in English to translate it themselves) and translate it to English: _use_ the fact that English _is_ the common language to increase the reach of non-Western developers! --- ### Visual Design The _language_ design is great. The landing page/docs/etc...? Well, we're *working* on it. Note: One of the areas where you could move the ball down the field fastest in the Rust community is with **_visual_ design**. (To be clear, the _language_ design is great!) But our websites could sometimes use some work. --- #### Visual design: it's not just us This is just not what "systems programmers" are interested in. So: bend the curve again. Make Rust stand out in this area. Note: Systems programming language types have historically _not_ spent a lot of time on the _presentation_ of their tools. In part this is just a matter of what these kinds of languages have been oriented towards: if you spend all day hacking on kernel code, you're _likelier_ to be a person for whom user interface and visual design is less interesting than, say, optimizing memory performance or minimizing the number of cache misses a given approach has. But presentation _does_ matter, and it matters especially as we want to enable more and more people to be able to write this kind of code. Speaking frankly, though I've spent a large chunk of my career to date writing systems-level languages, I've found the way a lot of these tools are presented to be a huge turn-off, and at times a barrier even to getting them working for me locally. Perhaps the most egregious example of that was some of the "documentation" – I'm not sure I should even call it that! – for Fortran, when I was first getting started programming back in college. The presentation of the material was essentially hacker-ish in a _bad_ way: no CSS, no attention to organization of the material, no structure to help you find your way through it. --- #### Visual design: how * If you're an expert or just a talented amateur, please pitch in * If you're just flat bad at design (it's okay!), choose good tools * Wing * Pure.css * Skeleton * Think about information hierarchy, a.k.a. outlines Note: You can help here even if you're not especially comfortable with visual design if you're willing to spend just a little time on it! For example, you can simply help a team adopt something like Bootstrap. Yes, it'll look like many other open-source projects out there. But it won't be horribly, catastrophically ugly and unreadable! Or you can do something even simpler – you can use a dozen lines of CSS and have something that's responsive on small screens, much easier to read than the unstyled defaults, and much nicer-looking to boot. So don't think that just because you aren't a design expert means you can't help here. But if you _are_ a design expert: **_please help here!_** Just as important as the _visual_ design is thinking about and actively designing the **information hierarchy** of your content. What leads to what? Which pieces go together, and which pieces can be broken up into their own pages or sections within pages? Think about the content like an _outline_. Many sites don't have any such structure to them; they're kind of haphazardly cobbled together. If you can help the maintainers with the _structure_ and _organization_ of their content, that can make an enormous differences as well. --- ### Blogging It's okay if it feels hard. Writing words ≠ writing software. But you can do it! Note: One of the other big ways you can help a project may not even end up in the repository at all. You can _blog_. I know blogging can seem intimidating, for many of the same reasons that writing documentation can. Technical writing is hard, and it's a completely different skill from programming. But it doesn't have to be amazing; it just has to get the information out there – and you'll get better as you practice. --- #### Blogging: "Easy Mode" > Just write down what you're learning. —Me, just now Note: You can start on "easy mode", too. I mentioned this earlier when talking about documentation, but "just write down what you're learning" is an incredibly effective technique for generating content. If you look at a lot of the technical blogging I've done over the years, it has been nothing more complicated than "here is what I just learned." And if you want a _superb_ example of this which is _very_ different from mine, take a look at the work that Julia Evans does on her blog! She regularly writes down, in an inimitable way, highly technical ideas she's just learning. If you want someone to make arcane Linux command line tools seem amazing and approachable, her blog is your ticket. --- #### Blogging: good examples Two totally different writers doing great work: * Vaidehi Joshi: "Basecs", intro to CS * Julia Evans: _what I just learned_ + comic illustrations Note: But even beyond "what I just learned," blogging is a superb way for teaching in general. Over the course of this year, for example, Vaidehi Joshi has been writing what is essentially a friendly introduction to computer science on her blog on Medium. This is a totally different style of _content_ (as well as of presentation!) from the kind of "what I just learned" content that Julia Evans writes, but it's also really effective, because she takes her knowledge and translates it into something others can pick up. That's obviously more work than just writing down things you just learned, but it can also pay really high dividends as others are able to substantially deepen their knowledge. --- #### Blogging: all the options! * one-offs, or series * technology: * _introduce_ it * _deep dive_ into using it * explain _how it's built_ * _critique_ or _highlight_ problems * demonstrate _integrating_ different parts of the ecosystem * _invite feedback_ on your own projects Note: In blogging, as in documentation, there is a whole spectrum of basic teaching content you can contribute! And communities need the whole spectrum for simple introductions to extremely thorough, advanced tutorials. But blog posts can also be much more versatile than traditional documentation. * **They can be one-offs, or series.** You can give a topic as much depth, or as little depth, as you _care about_ or _think it deserves_. I wrote an 18-part series comparing Rust and Swift, and it could have been 30 parts if I hadn't eventually gotten derailed. That's not _documentation_, but there's a lot people can learn from those kinds of things. * **They can introduce a technology, or dig deep into how to use it, or how it's built.** You're not limited to just one particular tack when blogging. Is your interest in the specific implementation details of some corner of the compiler? Write about that! Is your interest in how a given Rust library solves a specific kind of problem you've run into with another library, or with a similar library in another language? Write about that! You get the idea. * **They can critique or highlight problems with specific pieces of the ecosystem!** A careful, well-articulated, critical blog post can do wonders for showing the problems with a given approach and can even sometimes help suggest the right solutions to those problems. I've repeatedly watched, for example, as people have blogged about their struggles getting their heads around the Tokio tooling; the result has been a _lot_ of work by the Tokio team to respond to those problems. The more thoughtful and careful you are in that kind of criticism, the better! Good criticism is _incredibly_ valuable. Because we all have blind spots, and someone else's perspective can help jar us out of those. * **They can show how to _integrate_ different parts of the ecosystem.** For example, as part of the "Increasing Rust's Reach" initiative, Ryan Blecher recently wrote up a detailed walk-through on how to use the Diesel ORM and the Rocket web framework together to build a small blogging engine. That's _huge_! It makes it that much easier for someone who's just starting out with Rust, coming in from something like Python or Ruby, to dive in and get that intensely rewarding feeling of _having built something_ in a relatively small amount of time. That's also helpful because (almost) no one is building something with _just_ Diesel, or just _any_ crate. A huge part of what every software developer does is about fitting together other pieces of software. * **They can invite feedback on your own projects.** Talk about what you're doing, what your stumbling blocks are, what you don't understand. People will often show up and help you with comments and clarifications! And that's just scratching the surface. Blogs are incredibly versatile, and you should lean on that. --- ### Audio and Video Not just words! Noises and pictures, too! --- #### Audio: podcasts * Not everyone learns the same way. * Lots of people have commutes. --- #### Audio: but there are already podcasts ![New Rustacean](http://cdn.chriskrycho.com/images/talks/rbr_2017/newrustacean.png) ![Request for Explanation](http://cdn.chriskrycho.com/images/talks/rbr_2017/rfe.png) ![Rusty Spike](http://cdn.chriskrycho.com/images/talks/rbr_2017/rusty-spike.png) Note: Everything I've talked about so far has been in written form. But audio and video media can also be really helpful. Not everyone learns best by reading. And not everyone has tons of time to sit down and read a book every day. One of the reasons I started the New Rustacean podcast is that it gives people a way to get up to speed on the language while on a daily commute. But there's still a _huge_ need for more audio and video content in this space! One podcast is not enough! _Two_ podcasts is not enough! Seriously, not even three podcasts is enough! So I'm laying down another challenge: there's plenty of room for more, and more kinds, of audio content in this ecosystem. --- #### Video People have different learning styles! People loved RailsCasts. It was a bootstrapper. We could use the same! If you have skillz with video, use them! Note: There's also a huge opening for people to produce good video content. I've heard often from people that things like RailsCasts were essential in helping them learn the Ruby on Rails ecosystem. We _need_ video tutorials which might look kind of like that, or like the kinds of things I'm doing on the podcast. If you have any skill that way, and any interest in teaching, you should make Rust videos – there aren't many out there. --- #### Video: what There are lots of options: * make screencasts * live-stream working on open-source * live-_pair_ working on something * …lots more you can think of! Note: Another, totally different tack you can take with video is _live-streaming_. Sean Griffin has done this at times, and I've actually done it just once, and it's a ton of fun – and it can be incredibly illuminating for other people to see how you work and how you solve problems. --- ### Talk to people * IRC/Gitter/Slack/Discourse * Meetups * Conferences Physicality matters. Presence matters. (We know this! We're at a conference!) Note: You can also host or help with a local meet-up! For a lot of people, one of the major challenges of learning _any_ new piece of technology is that – even with IRC and Gitter and Slack and so on – you can feel isolated and alone. And people can help you solve problems in person, and make you feel supported in person, in ways that even a great community can't really manage online. So _go_ to meet-ups, at a minimum. And help the organizers. And if there isn't a meet-up in your community... you can start one! The #rust-community team has a ton of resources --- ### Being inviting What about all you old-timers? You still have things to contribute. _Welcoming_•_Mentoring_ Note: Last but not least in this list of _how_ to be a contributor, I want to take a minute and talk about "being a contributor" to those of you who've been contributors for a long time. Some of you have been shipping open-source software for years – some of you even for decades. Much of what I've said so far is old hat for you. Maybe not the design bits quite so much! But you've been doing this for a long time, and you're not trying to get over the hump of making your first contribution. You have other things to contribute here: * The most important thing you can do is practice **welcome people.** The Rust community does this well, in general, but it's something we need to keep in front of us as a goal as the community grows. It's easy to get frustrated with newcomers as your project grows, demands on your time increase, and your work as a maintainer seems less like fun and more like a second job. But continuing to actively welcome newcomers in is _incredibly_ powerful. You can make it possible for people to go from zero to really making a difference. And remember: so once were you. None of us started out as magical wizards of Rust and open-source. * The second big thing you can do is **mentoring.** As I mentioned, I'm now the maintainer of one of the core pieces necessary to make Ember.js and TypeScript play nicely together. But while I've done _some_ writing-of-code with that, a much larger part of my current and future work there is about helping other people learn TypeScript well enough to start using it in their apps and add-ons. But the flip-side of that is: even a fair bit of the code I _have_ written, I was able to write because someone more comfortable with some of the infrastructure mentored _me_ through its quirks and oddities. --- ## When & where to contribute Note: The last thing I want to touch on is _when and where_ to contribute. There are two things I'd suggest you should consider here: --- ### When & where: you Where are _you_ in the process of becoming comfortable with contributing? * Just getting started? * Already comfortable? Note: If you've never done any open-source work at all before, that's different than if you've gotten pretty comfortable with it in a different ecosystem and are just figuring out where to make yourself useful in _this_ ecosystem. --- #### When & where: if you're just getting started 1. Look for these! ![help wanted](http://cdn.chriskrycho.com/images/talks/rbr_2017/help-wanted.png) ![help wanted](http://cdn.chriskrycho.com/images/talks/rbr_2017/easy.png) 2. Pick big projects! Note: If you're just getting started, I'd pick a big project with lots of those "Help Wanted" and "Mentoring" and "Easy" tags on issues, and let the size of the project help you out. Those are projects that are _used to_ helping people make their first contributions. Crazy as it seems, something like Servo can actually be an _easier_ place to start out that a much smaller project. Sure, the technical lift is higher, but there are also a lot more people actively invested in your success there. --- #### When & where: if you're experienced 1. Find smaller projects. 2. Pick something interesting which could use the help. (Remember: more work than hands!) Note: On the other hand, if you're already comfortable contributing and have some idea what you're best at, you might look around and find smaller projects with fewer contributors which look interesting and _could use the help_. Because again, there's always more work to do than hands to do it. --- #### When & where: project lifecycles Where is a given project at in its life-cycle? * small project, basically done? * need docs? * big project, a billion needs? * etc. Note: The second consideration dovetails nicely with that: **where is a given project at in its life-cycle?** As enthusiastic as you might be about some project, if it's a small project and it's already in a "basically done" state, well... that's probably a lot less useful a place to invest your time _if_ you're focusing on code. On the other hand, it's often the case that projects are "done" in terms of code, but desperately need help with documentation, their web site, etc. Big projects, or projects just starting out, are often better places to dig in if you're really looking to flex your coding muscles (but both of them _also_ usually have huge needs in terms of all those non-code avenues we talked about). Think about both of those, and then see if you can pick a project that's a good fit for your current skillset and comfort level and jump in! --- ## Conclusion Note: And that's a good place to wrap things up! I hope you're feeling like _you can do this_. Because you can. Open-source a project of your own and see where it goes. Write a blog post. Add some docs. Open a PR. Record a podcast. Make some videos. Start a meet up. Become a contributor! --- ## More info * * * * `#rust`, `#rust-community`, `#rust-internals`, etc. on irc.mozilla.org ================================================ FILE: docs/bonus/13-silly-mistakes.md ================================================ # Bonus: I Still Make Silly Mistakes Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is a bonus episode: I Still Make Silly Mistakes. ## Sponsor: Parity First up, Parity is back sponsoring the show again because they want *you* to come write Rust with them! Parity is advancing the state of the art in decentralized technology, and they’re using Rust to do it, leaning hard on its trifecta of performance, reliability, and productivity. They're building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Two of the larger projects they're working on are: Substrate, a framework for building blockchains, and Polkadot, a platform leveraging blockchain tech for scaling and interoperability in decentralized systems. If that sounds interesting, check out their jobs at ! ## That mistake… So, the mistake I titled this episode after. Every time I draft an episode of New Rustacean, I start by writing out a script for it, long-form, in my preferred Markdown editor. (You can find those scripts in the show notes!) When I record the show, I’m reading that script—usually with some minor improvisation. One of the things I do as I’m writing is include links inline in the script. I do that for two reasons: - first, so that anyone who is reading the script has an easy way to link to the things I’m talking about throughout the episode - and second, so that when I pull that script over into the repository for the show, I can just pull those links out and put them in the show notes The first part works fine. Pulling the links out for the show notes has increasingly annoyed me, though: I have to go through and manually pull out each link from the text, and while that’s not a *ton* of work, it’s repetitive and error-prone. And “repetitive and error-prone” is basically the working definition of what software is good at! So I figured: hey, here’s a chance to play with a couple data structures I’ve not spent much time with in Rust and get more familiar with the [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) crate, which has a nice API for dealing with Markdown! (As I mentioned in Part I of the Rust 1.31 and 2018 Edition news episode, I basically default to Rust for these tasks at this point: it takes me about the same amount of time as doing in a scripting language would, and I enjoy it a lot more.) So I did what I normally do in these kinds of situations and ran `cargo new extract-md-links`. I pulled in the `pulldown-cmark` in my `cargo.toml`, and debated whether I wanted to pull in [the `structopt` crate](https://github.com/TeXitoi/structopt) for command-line argument handling—and decided against it because I figured: all I need to be able to do is pass in a single argument and this is a private tool for my very specific niche problem. No problem; I’ve parsed arguments from the command line manually for over a decade! Right? Wrong! I whipped up my main function and started trying to load a test document to start on the link extraction, figuring that would be the meat of this particular little problem. And then I started seeing an error that made *no* sense to me: `"stream did not contain valid UTF-8"`. What. Look: I *know* this file is valid UTF-8. It’s a blog post that currently runs through a Python-powered static site generator; it wouldn’t even have successfully published if it were *not* valid UTF-8. What's more: the file opens as valid UTF-8 in Visual Studio Code and Sublime Text. It validates properly as UTF-8 when I dump it into an online UTF-8 validator. It loads properly if I open a Python REPL and load the exact same path I was passing to my little Rust tool! At this point, as you can probably imagine, I started to feel like I was losing my mind. I hopped into the Rust Discord channel and started asking *really* basic questions about the things I was seeing. As an aside, if you've never just hopped into one of the Rust chat communities online, you should do that the next time you get stuck. And the rest of this story is a great example of *why*, but the short version is that the Rust community is *incredibly* helpful. Even for silly problems where the question-asker really ought to know better! But we'll get to that. So I started describing my problem, and a few other Rust users—especially @alercah—started asking helpful questions and offering helpful comments about the file I was trying to work with: - **What’s the first byte?** So instead of running `std::fs::read_to_string`, I used `std::fs::read`, which gives you back a `Vec` if it succeeds. It succeeded, so dumped the first byte. - **That doesn’t seem right; what’s the *second* byte?** At this point I just grabbed the first *eight* bytes the same way and shared those. - **Those are definitely not valid unicode. What’s the file?** I linked directly to the file I was trying to load from my blog source on GitHub. - **That file starts with different bytes than the bytes your Rust program is reporting.** And indeed, it started with the bytes I’d have expected: three hyphens (which are what start a block of YAML metadata for my blog posts). That last point had me *truly* confused. How in the world could two different people read the same file and get different results? And this of course was the key to the whole thing. But I'm getting ahead of myself again. My next step was to just dump the minimal set of code to reproduce this program straight into a code block in Discord, along with the actual Cargo command I was running and the actual error I was seeing. And then @alercah spotted my problem, and it turned out it had nothing at all to do with the file I thought, or with unicode at all. My problem was simply that I was *opening the wrong file*. You see, the first argument to a program is always the name of the program itself. There’s good reason for this; I’ve linked [an interesting discussion][unix] in the show notes (using this tool, which now works!) about why you might want the same program to be able to be called with different names and do different things in those circumstances. That's all just fine and dandy. Except that I was thinking the first argument would be the thing I was passing to the program: the path to the file I wanted to process. Instead, it was, you know: not unicode. Because it was a binary: the Rust program I was running! Once I grabbed the *second* argument, not the *first*, everything just worked exactly the way I expected. [unix]: https://unix.stackexchange.com/questions/315812/why-does-argv-include-the-program-name "Why does argv include the program name?" So that's what happened *technically*, that's the bug. But, and this is the actually interesting part of this experience, I think: you may recall my comment a minute ago that I’ve been doing this—parsing command line arguments—for over a decade! And I mean that literally: I first parsed command line arguments manually in Fortran and Java programs in 2008. This is a quote-unquote “rookie mistake.” And I laughed *really* hard at myself when I realized what had happened because it's such a "rookie mistake"! But of course, that phrase is really misleading. “Rookie mistake” suggests that these kinds of mistakes are specific to rookies, and the reality is that they *aren’t*. I'm not a rookie a decade in, at least not at this particular thing. But these kinds of things happen to all of us. And "these kinds of things" are just mistakes that come from *unfamiliarity*. Being new to programming entirely is one reason you might be unfamiliar with something. But just being rusty—no pun intended!—is another reason you might be unfamiliar with something! I haven’t had to hand-parse an argument in about five or six years, because I’ve been using something like [Python’s `argparse` library][argparse], or [Commander in Node][commander], or [clap] and [structopt] in Rust! And that meant it was easy to forget this kind of thing because I just hadn’t had to do it manually for such a long time. So that was the first reminder: *everyone* makes "rookie mistakes," because they're not really *rookie* mistakes; they're unfamiliarity mistakes. [argparse]: https://docs.python.org/3.7/library/argparse.html#module-argparse [commander]: https://github.com/tj/commander.js [clap]: https://clap.rs [structopt]: https://github.com/TeXitoi/structopt The second good reminder for me in this was actually from the feeling of frustration itself. It reminded me of what it’s like to be just starting out—to be a rookie!—to be looking at a compiler message that seems like it’s trying really hard to be helpful, but which is clearly telling you something that isn’t *exactly* the problem: it's not the *root* of the problem. “Yes, it’s true," I was saying, "that this is not unicode. But I have no idea *why* it isn’t unicode!” And even when you’re a decade along in your career and have generally developed a reasonable set of debugging techniques and intuitions about why things go wrong, things like this can be totally mystifying—still! And this should remind us—it reminded me—to be sympathetic to people just getting started—because even things which are totally obvious to us can be genuinely confusing to newcomers, *or even to us ourselves* with just a little distance from the specific expertise we’ve developed! ## Outro Anyway, that’s my fun story and my two takeaways about a silly mistake I made recently; I hope it’s helpful and encouraging when you make your own silly mistakes or when you see someone make what seems like a silly mistake! Thanks as always to this month’s $10-or-more sponsors: - Soren Bramer Schmidt - Graham Wihlidal - Benjamin Manns - Matt Rudder - Bryan Stitt - Brian McCallister - Evan Stoll - Oluseyi Sonaiya - Nathan Sculli - Ryan Osial - Martin Heuschober - Andrew Dirksen - Daniel Collin - Daniel Mason - Dan Abrams - Nick Gideo - Behnam Esfahbod - Scott Moeller - Adam Green - Nicolas Pochet - Alexander Payne - Nick Stevens - Peter Tillemans - Michael Mc Donnell - James Hagans II - Joseph Schrag - Raph Levien - Chris Palmer - Anthony Deschamps - David Carroll - Jerome Froelich - John Rudnick - Jason Bowen - Ramon Buckland - Embark Studios - Johan Andersson - Jonathan Knapp - Rob Tsuk - Jako Danar - Paul Naranja - Chip You can sponsor the show at patreon.com/newrustacean or via other services listed on the show website, . There, you’ll also find show notes, including links to things I talk about, scripts, code samples, and interview transcripts. The notes for *this* episode are at . Please recommend the show to others if you like it, whether in person, via your podcast directory, or in various media online! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending men an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/bonus/14-my-workflow.md ================================================ # Bonus: How the Sausage Gets Made Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust Programming Language and the people who use it. This is a bonus episode: How the Sausage Gets Made! ## Sponsor: [Parity](https://parity.io/jobs) First of all, I’m really pleased and grateful that Parity continues to sponsor the show, and it’s because they want to hire *you* to come work in Rust with them! Parity is advancing the state of the art in decentralized technology, and they’re using Rust to do it, leaning hard on its trifecta of performance, reliability, and productivity. They're building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Two of the larger projects they're working on are: Substrate, a framework for building blockchains, and Polkadot, a platform leveraging blockchain tech for scaling and interoperability in decentralized systems. If that sounds interesting, check out their jobs at ! ## Conferences Second up, it’s time for me to mention some Rust conferences! First, and most urgent is RustLab, to be held in Florence, Italy, this June 28–29. I call it the most urgent because the CFP closes tomorrow, March 24! (I meant to have this episode out a week ago! Whoops!) Second is RustConf, being held August 22–23 in Portland, Oregon. Once again I’m on the program committee, and once again we’d love to have you submit. It was a great conference last year, and I hope to have an equally great program this year! And hey, I’m looking forward to being in Portland again, as I was this week for EmberConf—it’s such a fun city! Third, near and dear to me (I seriously could not be more excited) is Colorado Gold Rust: a brand new regional Rust conference being held in Denver, Colorado, on September 20–21. I *will* be there, and I will almost certainly be there in a very official New Rustacean way! Stay tuned for details on that as we hammer them down. Finally, Rust Belt Rust is being held this year in Dayton, Ohio, on October 18–19. The calls for proposals for Colorado Gold Rust and Rust Belt Rust are not yet open, but I will certainly mention on the show when they are. ## How I Make the Show Okay, so today’s episode is a little unusual for the show, but I get asked questions about how I make the show and about a number of small but important decisions I’ve made along the way often enough that I thought it would be worth setting this all down in one place, so that I can have an easy place to reference when those questions inevitably come up! I want to note before I dive in, though, that what follows is *my approach and process*, as it has evolved over the course of the show and as a relatively financially successful show with a solid listener base. It is *not* my recommendation of how *you* should produce a show if you decided to start one! If you're interested in my thoughts in *that* direction, you should check out the two guest lectures I delivered on the subject at North Caroline State University back in the fall of 2016, both linked in the show notes ([A], [B]). [A]: https://winningslowly.org/bonus.03/ [B]: https://winningslowly.org/bonus.04/ ### Prep I also have a confession: I drafted this episode back in January, because I *knew* that I’d be super busy right now in March because I was teaching a workshop on TypeScript again at EmberConf, and trying to get out *any* episodes in March last year just about did me in! But that leads me into the first bit of how the show gets made: these episodes are all scripted top to bottom. That wasn’t always the case. The first few episodes of the show, I just wrote outlines and winged it. That was… not a good idea. I managed it okay, but if you go back and listen to those episodes, you can *tell* I’m winging it, and not in a good way. There were two big problems with doing it that way for me. 1. The first problem was that I had to record basically as soon as I finished learning something, because there was no way that an outline was going to do the job even a few days or a week later. My goal from the start has been to make this a top-notch resource that would have years of value to people, and the deeper into the language I got, the less comfortable I was with just saying stuff off the top of my head, instead of writing down *exactly* the right thing to make sure I got it right. So, a few episodes in, I started scripting the episode top to bottom. And, again: you can tell! It's obvious that I'm reading a script, both in the sense that it's obviously not just off-the-cuff (and it's a little bit less natural), but also in the sense that I can be much clearer and more precise as a result, and hopefully that tradeoff is worth it. Of course, it doesn't protect me from making mistakes! You can check out even a few recent episodes and note that there are corrections in the show notes! It does mean those mistakes are much less likely to happen, and they're typically smaller! 2. The second problem in doing it off the cuff was the editing job. So, here's the thing: when I edit a podcast, I *really* edit a podcast. I cut out umms and uhhs, and long pauses, and coughs, and so on. If I stumble over something, I nearly always back up and say it again. If, when I'm speaking from the script, something just *sounds* wrong, I back up and say it a different way. But those kinds of stumbles and things which made me need to edit happened a *lot* more when I was recording everything off the cuff, unscripted. That in turn meant that I had to spend more time editing the show, rather than doing, well, literally anything else! And as much as I enjoy editing podcasts—it's actually quite pleasant work for me!—it's not something I want to spend more time doing than actually *necessary*. Scripting lets me make a tradeoff: I spend a lot more time in up-front preparation, in exchange for a lot *less* time spent editing… and, as a bonus, I get scripts that I can make available with the episodes for people who prefer reading over listening, or for people who just want to go back and review the material in a different medium later. ### Recording Given that kind of prep work, producing the show is pretty straightforward most of the time! I'm just recording off of a script! Even when I do have guests, they have all been pretty easy to coordinate with. We just set up a Skype call (or something like that) and I split apart the guests' audio from mine so I can do that same kind of careful editing on both sides of the recording. I'm on a Mac, which means there are a bunch of *really great* tools for these kinds of things—in particular, [Audio Hijack] and [Loopback] from [Rogue Amoeba] have been game-changers for me when dealing with recording. Audio Hijack also supports *streaming*, so I hook it up to an [Icecast] server and broadcast my live recording sessions to the internet sometimes (like right now!). [Audio Hijack]: https://www.rogueamoeba.com/audiohijack/ [Loopback]: https://www.rogueamoeba.com/loopback/ [Rogue Amoeba]: https://www.rogueamoeba.com/ [Icecast]: https://icecast.org When I'm recording, whether alone or with guests, I take note of any obvious moments where I need to make an edit—I just write down the time stamp of my recording from Audio Hijack in a notes app, as a Markdown-style to-do list item. If I'm recording with guests, I also write down anything they mention that seems interesting and worth linking, so that I can use it for the show notes later. For solo episodes, I actually build everything I need for the show notes during the scripting process: I add links to the script wherever I mention a particular topic, and I built [a small tool (in Rust, of course!)][extract] to extract those links from the script to drop into the show notes when I'm done. For teaching episodes, I also spend the time building out the example code—both as a teaching resource and also just to make sure I understand things correctly! [extract]: https://github.com/chriskrycho/extract-md-links ### Editing Now, once I have all the audio in hand, I do the editing work I described a minute ago. I start by preprocessing the audio with a *suuuper* fancy tool called iZotope RX, which is worth its weight in gold for dealing with things like noise removal and cleaning up weird artifacts… but also you will pay your own weight in gold for it. Once I have preprocessed the audio, I switch into editing mode. Because I've usually written down most of the major edits, it doesn't normally take me very long. I'm using Logic Pro, and it gets the job done *just fine*, though it's pretty obvious that it's not really designed for podcast production. (When traveling I sometimes also use Ferrite, an iOS app, which is *incredible* value for money: full purchase is something like $20 and it's an absolutely fantastic podcast editing studio.) My workflow is basically: cut out and rearrange as necessary for any of the flubs I made along the way and took notes on, then use Logic's handy strip silence tool to remove any particularly long gaps. I then listen through to the whole episode, pulling together all the places where there was silence, and adding in the musical cues for the intro, an initial sponsor read if there is one, and the outro. This is also the phase where I sometimes turn mistakes into bloopers—only if they're actually good or funny, though. I also add chapters marks into the audio, usually just corresponding to the section headings in the script, which get exported with the WAV file when I'm done. I use a free tool called Forecast to convert that into an mp3 file with chapters in it, and upload that to my hosting! ## Publishing and Hosting So, speaking of hosting: how do I *publish* the show? Well, you can see that the website just rustdoc, of course, and I talked about *why* I did that all the way back in [the very first proper episode of the show][e001]. But if you know how podcasts work, you know that I need an RSS feed, and one set up to include downloads. And rustdoc… doesn't even know what RSS is, much less how to generate one for a podcast! I *could* write the RSS feed by hand, but happily there's an app for that. I use a tool called Feeder which generates RSS feeds with just about every option you could imagine, including podcasting—I basically just copy the show notes material into a standalone Markdown file and pipe that into the "notes" section for each episode in Feeder, and then my build process for the show pulls the generated feed output into the right location. [e001]: https://newrustacean.com/show_notes/e001/ The show HTML (including that RSS feed) is all just hosted via GitHub pages. I currently use Backblaze's B2 service—which is effectively an Amazon S3 replacement—to host the audio files, because they're quite reliable and extremely low cost. That setup is one of my favorite things things about podcasting—simple file hosting and an RSS feed is all you need. It's all just built on open web tech! ### Google, Spotify, and Stitcher And that leads me into the last part of this discussion—an answer to the question I get fairly often: Hey, can you add the show to Google Play Podcasts or Spotify or Stitcher? And the answer is: I could, but I won't. I'm not particularly ideological about many things in software—I save that for the theological side of my life!—but one thing I'm deeply committed to is the open web. The open web is an amazing thing: for all its messiness and all the nasty things that exist on it, the fact that I can put up a blog or a podcast using free, open technologies available to everyone is *amazing*. The fact that people from all over the world can listen to this because of that still astounds me, and I still think it's wonderful. And podcasting, like blogging, is an incredibly simple technology built on nothing but file hosting and RSS. Unfortunately, Stitcher, Google Play Podcasts, and Spotify's podcast service all aim to make something *different* out of podcasting in their own ways. They're not the only ones, but they're the ones with the most influence. From a technical perspective, all of those services re-host—and, just as importantly, re-compress—my audio. That annoys me first and foremost because I've made extremely careful and considered decisions about my audio; I don't want anyone else changing that. It frustrates me second because they do it primarily because it gives them more insight into their users' behaviors, and it turns out there's money to be made there. Although there are technical benefits to them—controlling that means they have command over streaming, the source won’t go down, etc.—the deeper reasons are those economic reasons. And that leads me to the final reason I consistently refuse to put *any* of my podcasts on those services or any others like them which may appear in the future: they're interested in monetizing my content and your listening habits for themselves—not for you and not for me. In particular, they want to do that by analyzing everyone's listening habits and trying to deliver more targeted ads. I'm simply not on board with that model. Finally, in each of those cases they clearly want to be *the* source—the sole or primary gatekeepers and middlemen—for podcasting. And I have no interest whatsoever in contributing to the centralization of yet another open web standard. We don’t need a Facebook for podcasting. Now, to be clear, I don't think it's wrong for anyone to use those services, and I don't think there's anything wrong with other podcasters making different choices about these particular tradeoffs! Depending on what your podcasting needs look like, it may be worth dealing with those downsides as part of a larger play to be financially viable, or because you’re part of a podcast network that is on those platforms, or simply because those tradeoffs don’t bother you as they do me. That’s legitimately fine: this is a complicated space when it comes to the moral reasoning! But this is a place *I* draw the line. If Google, Spotify, and Stitcher decide to work the same way everyone else does—*with* the open web—they're welcome to my shows. Because, after all: it's just RSS! But so long as they're trying to do an end-run around the open web for better ad monetization, I'm not interested. ## Outro Anyway, that's it for this bonus episode. I hope it was interesting, and if it piqued your curiosity or encouraged a budding interest in podcasting, I do encourage you to check out the podcasting guest lectures I mentioned a few minutes ago—you can check them out in the list of bonus episodes at , and I've linked them both in the show notes! Likewise, if the ethics concerns of this particular episode are interesting to you, Winning Slowly is likely to be of interest in general. This season, my cohost and I are basically arguing it out every episode in the interest of finding a third way that is neither techno-utopianism nor radical techno-skepticism. ### Patreon Sponsors Thanks as always to everyone who sponsors the show! This month’s $10-or-more sponsors included: - Oladapo Fadeyi - Nick Stevens - Rob Tsuk - Embark Studios - Alexander Payne - Ryan Osial - Matt Rudder - Bryan Stitt - Graham Wihlidal - Daniel Collin - Oluseyi Sonaiya - Daniel Mason - Jako Danar - Raph Levien - Peter Tillemans - Soren Bramer Schmidt - Evan Stoll - Adam Green - Anthony Deschamps - Brian McCallister - Joseph Schrag - Jonathan Knapp - John Rudnick - Benjamin Manns - David Carroll - Behnam Esfahbod - Jason Bowen - Paul Naranja - Dan Abrams - Chip - Nick Gideo - Martin Heuschober - Scott Moeller - Jerome Froelich - James Hagans II - Nathan Sculli - Ramon Buckland - Arun Kulshreshtha - Michael Mc Donnell - Andrew Dirksen - Johan Andersson - Nicolas Pochet You can sponsor the show at or via other services listed on the show website, . There, you’ll also find show notes, including links to things I talk about, scripts, code samples, and interview transcripts. The notes for *this* episode are at . Please recommend the show to others if you like it, whether in person, via your podcast directory, or in various media online! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending men an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/bonus/burnout-script.md ================================================ # Bonus: Burnout Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust Programming Language and the people who use it. This is a bonus episode, on *burnout*. For today’s episode, I’m going to do something slightly different than usual. All the sponsors and show notes stuff will be up front in the next two minutes. After that, I’m going to talk about burnout and my experience of it—but there’s no script today. My *hope* is that hearing me talk about it, and talk about it “off script,” will help someone out there. So: let’s talk sponsors. ## Sponsor: Parity Technologies First, Parity Technologies is sponsoring this week’s episode because they want to hire you! Parity is advancing the state of the art in decentralized technology. Their flagship software is the Parity Ethereum client, but they're also building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Their next big project is Polkadot, a platform leveraging blockchain tech for scaling and interop in decentralized systems. Parity uses Rust for its trifecta of safety, speed, and correctness! If that sounds interesting, check out their jobs at paritytech.io/jobs. Thanks again to Parity! ## Patreon Sponsors Second, thanks to everyone who sponsors the show on Patreon! As of recording, there are 100 of you sponsoring right now, and I find that particularly amazing and encouraging in the midst of the burnout I’ve been experiencing. This month’s $10-or-more sponsors included: - Ryan Osial - Anthony Deschamps - Peter Tillemans - Nicolas Pochet - Marshall Clyburn - Martin Heuschober - Matt Rudder - Paul Naranja - Oluseyi Sonaiya - Hans Fjällemark - Dan Abrams - Michael Mc Donell - Nathan Sculli - Rob Tsuk - John Rudnick - Daniel Collin - Daniel Mason - Ramon Buckland - Joar Wandborg - Chip - Graham Wihlidal - Alexander Payne - Behnam Esfahbod - Raph Levien - Nick Stevens - Aaron Turon - Zachary Snyder - Chris Palmer If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, send a one-off at any of a number of other services listed at newrustacean.com, or get in touch directly. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for \_this\_ episode at \. If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. ---- Okay, so let’s talk about burnout. - what it isn’t - what it is - Mayo clinic guidelines: - Have you become cynical or critical at work? - Do you drag yourself to work and have trouble getting started once you arrive? - Have you become irritable or impatient with co-workers, customers or clients? - Do you lack the energy to be consistently productive? - Do you lack satisfaction from your achievements? - Do you feel disillusioned about your job? - Are you using food, drugs or alcohol to feel better or to simply not feel? - Have your sleep habits or appetite changed? - Are you troubled by unexplained headaches, backaches or other physical complaints? Mayo calls it: > a special type of job stress But the triggers aren’t just *job*-related Job-related causes Mayo suggests: - Lack of control. - Unclear job expectations. - Dysfunctional workplace dynamics. - Mismatch in values. - Poor job fit. - Extremes of activity. - Lack of social support. - Work-life imbalance. I add: - long-term stresses in family life, e.g. your dad gets a brain tumor or you’re a caregiver for someone - specific triggers can take “I’m stressed” -\> “burnout” - it gets worse if you don’t deal with it - how do you deal with it? - sleep - don’t overwork - friends - exercise - counselors! meds! ================================================ FILE: docs/bonus/translating-between-languages-script.md ================================================ # Bonus: Translating Between Languages Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust Programming Language and the people who use it. This is a bonus episode on translating between programming languages. ## Sponsor: [Manning Books/Rust in Motion](http://bit.ly/2OXnlEb) First up, a new sponsorship! I’m *really* excited to be partnering with Manning Books to bring you a discount on some *video content* they’ve put together. Even better because that video content is by Carol Nichols (whom I interviewed a couple years ago) and her husband Jake Goulding! I’ve been saying for years that we need more video content: it’s a huge way people learn. Manning’s Rust in Motion is one of the first major video courses for Rust I know of. You can get it for 40% off at [deals.manning.com/new-rustacean](http://bit.ly/2OXnlEb) – there’s a link in the show notes. That link actually gives you 40% off of *anything* at Manning, including their book *Rust in Action*, which is in early access preview. Thanks so much to Manning for sponsoring the show and building some great video content with Carol and Jake! ## Translating from TypeScript I’ve mentioned a number of times on the show that my day job is building a web front-end in JavaScript and TypeScript—these days, pretty much entirely TypeScript. I recently had an opportunity come up to work on a side project where I am converting some library code from TypeScript to Rust, to accelerate this project via WebAssembly in the browser. I hope to have more to say about that project in the future; for now, what’s most interesting to me for this little bonus episode is what that *experience* has been like. There’s an interesting nugget here for reflecting on programming languages and what makes them valuable. I’ve said to a number of people over the last year that writing TypeScript and writing Rust can feel very similar. Their surface syntax has a lot in common, and depending on how you write your TypeScript, the semantics can end up feeling relatively similar as well. “Depending on how you write your TypeScript,” is an important qualification. There are a *lot* of ways to write TypeScript, because there are a lot of ways to write JavaScript, and TypeScript is just type annotations on top of JavaScript. If you’re writing TypeScript like it’s C# or Java, it won’t feel much like Rust at all. But if, like me, you prefer a more functional idiom and you use TypeScript kind of like a weird, extremely verbose version OCaml, with carefully controlled mutation, well, it ends up feeling a lot like Rust. After all: Rust is kind of like OCaml, but with explicit control over ownership and mutation! So in my experience, writing TypeScript and Rust felt pretty similar, in very good ways, a lot of the time. But. Let me tell you. When you start trying to translate things from TypeScript to Rust, stuff gets really weird, really fast. One of the things that initially feels very similar between the two, for example, is the type system. And so far as it goes, that feeling is not totally wrong. Both languages give you generic types; both give you interface-like ways of expressing constraints and let you bound generics with those interface-like structures—literally `interface` in TypeScript and of course `trait` in Rust. There are important differences in both the surface syntax and the underlying semantics, especially in the languages’ type systems, though, of course. The most obvious difference at the *surface* is that TypeScript has a structural type system, where it only cares about the *shape* of the objects you pass, where Rust has a nominal type system: two structs with the same fields are still different structs, because they have different *names*. What’s more, TypeScript has anonymous, bare union types but doesn’t have built-in tagged unions like Rust’s enum types. So in TypeScript you can say something is a string or a number, without any wrapping name; but you have to write a ton of boilerplate to get the equivalent of Rust’s `enum` types. And vice versa: in Rust you get *tagged* unions for free, but you can never have a *bare* union type: you always have to do the boilerplate of wrapping those kinds of things in an enum. So there are real differences at this level! But while I thought those would be the thing that would end up leading to the biggest mismatch, it turns out that accommodating for *those* isn’t that hard. You have to write some enum types out more explicitly, and you can throw away some of the workarounds and boilerplate that come from not having Rust’s `enum` tagged union types in TypeScript, but it’s not that bad, because the semantics are relatively similar, even with those differences in surface syntax. No, what gets really weird is the combination of TypeScript’s `interfaces` *not* being isometric with Rust’s `traits`, and *ownership*. In retrospect, the latter should have been obvious, but the `interface`/`trait` distinction was a lot *less* obvious. Let’s start with the obvious one, and then we’ll use it as a way of circling back around to the `interface`/`trait` thing. TypeScript’s approach to interfaces and classes is (mostly) like interfaces and classes in most object oriented languages you’d be familiar with: both interfaces and classes can include both data and functions. Rust… doesn’t do that. At all. As we’ve talked about in recent teaching episodes, Rust makes a clean separation between *data* and *behavior*. `struct` and `enum` types have data. `trait` types have behavior. And never the twain shall meet. Layered on top of that is the ownership system: TypeScript is perfectly happy to let you have lots of shared mutable references to the same data, recursive types are be fairly idiomatic, and cycles between data structures are no big deal (though they *can* cause memory leaks if you’re not careful). All of this is perfectly normal for a garbage-collected language! Meanwhile, Rust has as its most basic distinctive the *every piece of data has a single owner* rule. Recursive types are *not* all that idiomatic, and have to be explicitly wrapped in some kind of pointer type; and shared mutable references to the same data are right out. Cyclical data relationships in Rust are just a quick way to pain: you can make them work, sometimes, but it’s hard and never natural. So if you go to try to translate a TypeScript `interface` straight into a Rust `trait`, or a TypeScript `class` straight into a Rust `struct`, *things get weird.* This is because of the real differences between the two languages is in their base semantics—the deep structure and most important constraints of the languages. These aren’t things that are apparent from surface syntax, since the surface syntax of the two is pretty similar! Now, as an aside, this doesn’t mean syntax doesn’t matter. People often step from “syntax doesn’t map perfectly to semantics” to “syntax is irrelevant,” but the second doesn’t follow from the first. Syntax can map more or less cleanly to the underlying semantics, and it can lead—or mislead—by the way it’s shaped. So what we ought to say is that while syntax matters, it’s far from the *only* thing that matters. What I have ended up finding as I’ve worked on this translation project is that sometimes an `interface` in TypeScript translates to a `trait` in Rust… but sometimes it should be a `struct` or an `enum`! It depends on how it’s used and what the mechanics in play are. Likewise, things like an abstract base class in TypeScript don’t have *any* corresponding notion in Rust, so you have to dig a bit on what the intent is and then spend a while thinking about how you might express that intent in Rust. More, sometimes it may not be possible to express exactly the same thing in Rust in any idiomatic way, or sometimes even at all. For example, as I noted a moment ago, TypeScript supports cyclical types: it’s just modeling the way JavaScript behaves at runtime, and JavaScript types can and do have cycles. If you want an object with a reference to its parent which references the item as its own child, well… Rust doesn’t have a fun time with bidirectionally linked tree structures. You can *make* it work with `Rc` (or `Arc`) and `Weak`, but if you then need to handle, say, partial equality with the `PartialEq` trait, you need to define local newtypes to avoid the orphan rule, and so on. The net of all of this is just an interesting little observation on the realities of how different languages lead us to solve problems in different ways. Things that make very good sense in TypeScript are so difficult or un-idiomatic in Rust that you would just *never* do it that way. And the inverse is true as well, of course! There are plenty of things that Rust’s type system makes easy that are much harder to do in TypeScript, since Rust can (and does) assume that its types are useful inputs for defining runtime behavior and TypeScript has to just erase all of its types entirely, with JavaScript’s runtime behavior only *hopefully* matching the types! And that is a good reminder of why I think being a polyglot programmer is *really good*. Different languages, even the ones which are superficially similar, help us *think* in different ways. ## Closing I’m sure I’ll keep learning as I keep pushing forward on this, but I thought it would make for an interesting little aside here—thanks for listening, and I hope you enjoyed it! Thanks to everyone who sponsors the show! This month’s $10-or-more sponsors included: - Behnam Esfahbod - Ryan Osial - John Rudnick - James Hagans II - Peter Tillemans - Alexander Payne - Michael Mc Donnell - Chip - Dan Abrams - Joseph Marhee - Bryan Stitt - Rob Tsuk - Daniel Mason - Oluseyi Sonaiya - Adam Green - Nathan Sculli - Graham Wihlidal - Scott Moeller - Joar Wandborg - Nick Stevens - Raph Levien - Daniel Collin - Chris Palmer - Anthony Deschamps - Nicolas Pochet - Bryce Johnston - Paul Naranja - Ramon Buckland - Matt Rudder - Martin Heuschober - Jonathan Knapp - Aaron Turon If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, send a one-off at any of a number of other services listed at newrustacean.com, or get in touch directly. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for \_this\_ episode at \. If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/bonus-2-script.md ================================================ Legacy Code =========== Intro (15s) ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is **Bonus Episode 2: Legacy Code** Talk (6-8m) ---- - Talking with a colleague about changes we're making to a codebase right now. - History: all but one major job or contract == maintenance. - The problem: a lot of times, legacy code is a mess. - The temptation: FIX ALL THE THINGS!!! - The other problem: stuff (usually, for the most part) actually works now - The solution: clean up your mess as you go. Be a good Boy Scout. Closing (1m) ------- ### Sponsors Thanks to Chris Palmer for sponsoring the show this month! See the list of other sponsors in the show notes. If you'd like to sponsor the show yourself, you can set up recurring donations at Patreon.com/newrustacean, or one-off donations at Venmo, Dwolla, or cash.me. ### Follow/support You can find show notes with detailed code samples illustrating these ideas, as well as links to things mentioned on the show, at NewRustacean.com. You can also follow the show on Twitter or App.net @newrustacean, or follow me there @chriskrycho. If you like the show, please rate and review it on iTunes to help others find it. Last but not least, I'd love to hear from you on social media, in the thread for the show on the Rust user forum at users.rust-lang.org, or via email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/bonus-3-script.md ================================================ Building as a Community ======================= Intro (30s -> 0:30) ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is **Bonus Episode 3: Building as a Community**. Normal episodes are 15--20 minutes long, but bonus episodes like this one are a bit shorter---usually under 10 minutes. I took a one-week long 8--5-every-day class three weeks ago, and then started a new job two weeks ago, which included getting trapped in New York City by a once-a-century blizzard, so I have not had time to put together quite as technical a talk as usual. But today's topic, community, is just as important for whether Rust succeeds in the long term--- maybe even more important---than some of the technical details we talk about week in and week out. Talk (6-8m) ---- - **A story (2m):** learning Fortran - **Another story (2m):** learning Rust - **Takeaways (4m):** 1. Community matters even for building something big and complicated, and you don't have to be a jerk to get really amazing results. Quite the opposite, in fact. (elaborate: Rust, Elixir, etc.``) 2. Building *as* a community matters as well. It's great that we're kind to each other---really great. But we should also actively help each other. This is true of any project you want to succeed. You'd be surprised how much open-source projects need help, and how often you're actually one of the best people *to* help. If you see a problem, you are often in the best position to fix it simply because you know the pain point. And if you have a good community, like we do in Rust, people will help you help them. Ask around, look at lists of issues, etc.---and even if an issue marked "easy" looks too daunting, give it a go. Find a project that looks interesting, or useful, and offer to help. People will help you learn what you need to know to solve that problem. You'll grow, the project will be in better shape, and it'll be a win all around. Closing (1m 30s -> TODO) ------- Next time, we're going to go for a high-level but extremely important discussion about type systems, both in general and specifically in Rust. Since Rust's type system is such a big part of its interest, and one of a few things that distinguishes it from languages like C or Java, I think it'll be fun and interesting to talk about that in a bit more detail. ### Sponsors Thanks to Hamza Sheikh and Chris Palmer for sponsoring the show this month! Check out the list of other sponsors in the show notes. If *you'd* like to sponsor the show, you can set up recurring donations at Patreon.com/newrustacean, or one-off donations at Venmo, Dwolla, or cash.me. ### Follow/support You can find show notes with detailed code samples illustrating these ideas, as well as links to things mentioned on the show, at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you like the show, you'd make my week by rating it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend! Thanks to everyone who's added corrections and fixed typos in the show notes; pull requests are great. I also love hearing from you! Definitely say hi on social media, add your thoughts in the thread for the episode on the Rust user forum at users.rust-lang.org, or shoot me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/bonus-4-script.md ================================================ # We *can* have nice things. ## Intro {>> 15s <<} Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is *Bonus Episode 4: We **can** have nice things.* ## News and Follow-up {>> 4m <<} First up, some news---and there's a bunch of it this week! Rust 1.8 was release this week! It's been just under a year since 1.0 came out, and in that time we've seen fairly dramatic movement forward in the language, but without any substantive breaking changes. Just about any package that built on 1.0 still builds, despite the language having gained a lot of new capabilities. I *love* that. There are a few nice changes in Rust 1.8: 1. The plus-equals and minus-equals and similar operators are now overloadable via the op-assign family of traits, like `AddAssign`. That's a small but very nice improvement; getting to a point where all those kinds of things are extensible via traits makes for a more consistent, and more robust, programming model for Rust. 2. The first steps toward building Rust itself with Cargo, instead of with Make, are now on stable. This is bootstrapping taken to another level entirely: we're headed toward a point when Rust itself will be used for all the pieces around building Rust. If you're worried about not-invented-here syndrome, that's a good caution, but having experienced quite a few different package managers and tools lately... I think this is a good move. Make is a great tool, but Cargo is a much better one for these purposes, and the combination of Cargo and crates.io is *really* good---far better than pretty much anything else out there. 3. In just a few release cycles, Rust will no longer require a special nightly build of Rust to build itself: it will always be built using the previous version of the compiler, so 1.10 will be built with 1.9, and 1.11 with 1.10, and so on. 4. There's a new tool for managing Rust installations currently in beta. It's called "rustup", just like the current standard install script, but it's actually a pure-Rust implementation of the multirust tool. If you're familiar with tools like rbenv, pyenv, nvm, etc., this is that kind of tool: it allows you to manage multiple installations of your language, and set local directory rules for which version to use, and so on. Try it out! Second, a quick note on scheduling: the last few weeks have been really, *really* busy for me between work, my Master's degree, and some family stuff. But I've had Rust on my mind a *lot*, between watching the 1.8 release come out, watching Sean Griffin live-code on Diesel a bit, and especially by way of comparison with all the JavaScript I'm writing for my day job. So here's a bonus episode, with the Strings episode to be recorded this coming weekend! ## Body {>> 7m <<} I've been writing a ton of EmberJS for my day job, and I keep looking around for something *like Rust* in the JavaScript world. There are plenty of compiled-to-JavaScript languages out there, from CoffeeScript (which kind of kicked off that whole trend); to things like TypeScript, which shows the influence of the .NET team and C# pretty heavily; to Elm and PureScript, which are heavily inspired by Haskell. But none of them have the really wonderful mix of pragmatism and elegance that seems to characterize Rust to me. Rust is a fairly unique mix, with its extremely capable type system, performance, and what we often call *ergonomics*---how it feels to use. It's no one thing: it's syntax and semantics; it's a strong, *expressive* type system; it's the lack of nulls; it's powerful enumerations; it's trait-oriented instead of inheritance-oriented polymorphism; it's the whole package together. Basically, every day I write JavaScript and look at the alternatives, or even fairly solid other languages like C#, the more impressed I am by Rust. People often wonder what the best way to learn a programming language is. The common answer is "just use it," of course: but how? How do you *start*, especially if it's not something you can use day-to-day for work, and if you don't have a specific project in mind for it? One of the best answers is: use it to build all the little tools you need for *other* projects. A colleague noted that the way he learned F# in a way that *stuck* was using it with the Fake tool to write (and now maintain) a bunch of our in-house tooling. You can do the same thing with Rust. Just write *something* in it. Because as much as Rust gets pegged as a "systems programming language" because it has the ability to do low-level work, the truth is that it's also just really good in its own right for *general* programming tasks. Over the weekend, I saw some posts on Hacker News about the Rust 1.8 release which hit on this same theme. Several users noted that they'd been using Rust more and more for the kinds of small projects where they once would have defaulted to something like Python. Between how solid a package management and build tool Cargo is, and the fact that once you get a Rust binary to *compile*, many times it already does what you want it to, it's extremely powerful. And it's also the kind of thing you can just install and run on *any platform*. Anybody who's spent time trying to distribute, say, Python or Ruby programs knows how valuable that is. Not having to install a runtime to install a program is a *big deal*. I was talking about this on Twitter in light of that thread, and someone responded exactly how I've felt for a while now: it "Feels like Python, runs like C." In fact, this is actually what attracted me to Rust in the first place. When I started reading through the book, I remember very distinctly thinking, "Huh. This is the first language I think might replace Python as my go-to tool in general." And that's been born out by the last eight months of using it for little things here and there. And of course that goes for other languages, too; you could do the same with Elixir, or Haskell, or whatever else. It might sound crazy to use Rust instead of Python for doing some relatively high-level work. Again: there's all that press out there about writing operating systems in it---and it's good at that. But that's not the only thing it's good at. The type system and good compiler mean that it's versatile and capable in all sorts of domains. Next time you need a utility... write it in Rust. You may be surprised at how straightforward it is, and you'll learn things about using Rust, and you'll come away with a better appreciation for just how well-designed the language is. I certainly intend to! ## Outro ### Sponsors Thanks to Hamza Sheikh, Chris Palmer, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at Venmo, Dwolla, or cash.me, or get in touch with me directly. ### Follow/support You can find links to those as well as to the discussion threads I mentioned at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. You can help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend! So do respond on social media, in the thread for the episode on the Rust user forum at users.rust-lang.org, or via email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/bonus-5-script.md ================================================ # Better than open source contributions ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is *Bonus Episode 5: Better Than Open Source Contributions*. ## News and Follow-up First, a quick explanation on the delay of this episode: we had a family health emergency come up---the kind that landed a family member in the hospital for several days---so recording this obviously took a lower priority. Podcasts are good and Rust is great, but family is far, *far more important*. As you'll see in a minute, that's actually especially fitting given the content of this particular bonus episode. One of the big highlights for me in the last couple weeks is the announcement of the open-source Xi editor project, which aims to be a performant, extensible editor with a Rust text engine backing it and native interfaces in Cocoa and eventually .NET, GTK, etc. This is incredibly interesting to me for a variety of reasons, some them algorithmic (like the fascinating *ropes* algorithm he's using to implement the text engine; and others architectural, like the planned structure for linking the front and back ends; and of course some simply Rustic: this is *exactly* the kind of thing I've long had in mind to use Rust for, and the reason I started learning it in the first place. I'll link the project in the show notes, and you should definitely keep an eye on it. One other thing to check out: for Rust's 1.0's one-year birthday, the Rust team launched a community survey. I've linked it in the show notes, so go fill it out! ## Open source Now, for today's topic. Over the last few years, I've often seen the suggestion that you need to be actively involved with open source software for the sake of your career. Last week, I saw someone say flat-out that he won't hire someone who doesn't do a bunch of open-source work in their spare time. This is, in a word, *nonsense*. To start with, I don't really buy the argument that it's somehow a mark of a good developer. I've had several jobs where it wouldn't have been remotely relevant---and for the job I have now, which is an absolute dream in many ways, I don't have any reason to believe the meager open source contributions I *had* made impacted the hiring decision whatsoever. And that's as it should be, because I think it would actually be a disaster if most companies started treating open-source contributions as a major component of a hiring decision. Or, for that matter, *any* component, for the vast majority of jobs. (The only exception is a job where you're being hired to work *on* open-source. But those are pretty rare.) Why does this even come up? Well, employers tend to care about open-source contributions on your resume for a couple reasons. 1. **They see it as a way to evaluate your code quality.** This is a reasonable desire, but there are lots of ways to do this which don't involve requiring open source work. One of my favorites, an idea o picked up from The Frontside, is for a company to hire you at their standard consulting rate for a day and just work with you directly. This gives you a good feel for the company, gives the people at the company a good feel for where your skills really are and how you work with a team, and---incredibly importantly---doesn't ask you to do something for free to prove your value as an employee. 2. **They see it as a sign that you're the kind of employee they want to hire, because they want people who do a lot of programming outside of work.** From companies like this, just run away. Basically, this means two things about the company in question: 1. They do not value anything about you except your programming interest. As I'll come back to in a minute, this is a profoundly misguided view of what makes for a healthy employee---because it's a profoundly misguided view of what makes a healthy *human*. 2. It drives the company toward a monoculture, and means it will miss out on a lot of other wake vey qualified and talented people, whose input and perspectives will be enormously enriching. While diversity can become a sort of totem, something people chase for its own sake, I think a wide variety of perspectives really is quite good for the work we all do. More than that, though: do you really want to work at (or be) the kind of company that turns down a programmer just because she's a mom who thinks spending time helping her kids with their homework in the evening is more valuable than doing open source software? Or because he's a son whose parents are ill and he takes care of them? Or because she's spending nights and evenings investing in community theater? Or any number of other legitimate, healthy, human reasons people have to do something besides *code* in their spare time? Don't get me wrong. I like doing software work for fun. I make a podcast about a programming language, for goodness' sake. But demanding that everyone fit that mold is incredibly shortsighted; it will make you build a pretty terrible company culture filled with people who are just clones of you. And it inherently devalues everything else. At the end of the day, you don't want to work for a company that's incapable of seeing things besides software as valuable. If "you must do open source" is one of their prerequisites, keep applying for other software jobs. There are more than enough to go around. But let's take this one step further: even the "we want you to have other hobbies" line you sometimes hear can be a problem. Some companies want you to have outside activities and not sell yourself to the job for reasons that are still, at the end of the day, purely mercenary. It's increasingly well-known that people are more productive on the job when they have healthy personal lives, so it's understandable that well-informed companies are starting to value that. But I think that, while that shift is good in one way, in too many cases it still comes down to a commoditization of people. In a way, it's worse than the more directly exploitative practices it replaces: it says that families and non-work hobbies are valuable not because they're good, essential parts of human existence as it is supposed to be, but merely as more means to the end of profit. And human beings and human relationships are not means, but ends in and of themselves. When we turn people's entire lives and all their loves into nothing more than another way to maximize productivity and profit, we have gotten things completely backwards. Now of course it *does* help, but that's because people are meant for more than work! We are not meant for less: work is good. Programming is good. Creating things and putting them into the world is good. But those things aren't everything, and we should never, *ever* make everything about them. Don't get me wrong. I'm grateful that my employer is quite serious about people taking care of their families and leaving work at work. And if you're running a business or managing a product team, you will probably find that people do give you better work when you encourage them to do things besides programming. But don't make the mistake of reducing people to levers for profit. And if you're an employee, don't make the mistake of letting someone demand that you make your life about the job---not directly and not indirectly. Be okay interrogating the way companies think as well as what they do, because *it matters*. It *really* matters. The best kinds of companies want you to spend time with your family and have things you're passionate about outside of work not just because it's good business, but because it's simply *good*. ## Closing In some ways, as much as I love talking about Rust---and as happy as I'll be to hop back into that next time---I think it's worth stopping to say things like this. Thanks for listening, and if you found this episode helpful, do please share it with friends or colleagues. ### Sponsors Thanks to Chris Palmer, Hamza Sheikh, Daniel Collin, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at Venmo, Dwolla, cash.me, or Flatttr---or get in touch with me directly. ### Follow/support You can find links to everything I mentioned at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. You can help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend! So do respond on social media, in the thread for the episode on the Rust user forum at users.rust-lang.org, or via email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/bonus-6-script.md ================================================ # It doesn't need to be sexy ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is *Bonus episode 6: It doesn't need to be sexy.* ## News and follow-up - Aaron Turon and Alex Crichton published their new `futures-rs` crate, which provides some low-level primitives for a concept variously called *futures*, *promises*, or *delayed* or *deferred* values. I'll link the crate in the show notes; it has some great documentation as well as being what looks to be a pretty solid implementation. I'll come back around and devote an episode to futures in the future. This is a huge thing for the ecosystem, and part of what makes it great is that it's not part of the language, but built on top of it---the language's core primitves expose everything required to do it and do it *well*. This will open a *lot* of doors for higher-level interfaces in lots of other libraries. - Closely related, Carl Lerche, the author of the Mio low-level I/O Rust library, recently published Tokio, a network application framework, which takes advantage of `futures` directly. - I just bumped into a project called Shadercat, by Claudia Doppioslash, who's already decently well-known for her work helping teach people about functional programming---but in this case, she's looking at doing graphics program with Unity and Rust. If those are interests of yours, you should definitely subscribe to the blog, which I'll link in the show notes. - _The Rust Programming Language_ is now a co-authored work by Steve Klabnik and Carol Nichols, who co-founded Integer32, the first Rust consultancy (which I mentioned a few episodes back). - Speaking of *writing* projects, keep your eyes open; I have a Rust-related writing project coming your way later this fall, which I'll discuss in more detail once it's out! Now, for today's discussion. ## What to build Over the past few months, as I've watched and participated in the Rust community, I've noticed a pattern (and I include myself in it): we glorify the compiler team and work. A lot of the focus in the community is on the language core itself. And this is a problem. Now, I get this: like I said, I've been guilty of that myself, right down to the kinds of things I've focused on in my "News" sections. The language is *cool*, and the team working on designing it and tweaking it is very talented. More than that, having a language moving forward at such an active pace is something fairly novel. To the best of my knowledge, there is nothing else quite like the pace of post-1.0 Rust development, where a language is simultaneously stable *and* improving its capabilities rapidly, making it better at solving many problems and capable of solving new ones. It's *exciting*. It's especially tempting because we can jump in and participate in helping improve the language itself---not an experience most of us have had in other language communities, even really great ones. There are a lot of upsides to just how open the Rust development process is, and this is one of them. But. *If* we want Rust to really flourish and succeed, we need to look more broadly and choose things besides the compiler to focus our attention on, and to lavish our praise on. And that's a two-fold change: 1. We need to keep our eyes open for other significant open-source projects in the community, and chip in on those. 2. We need to look around and note all the *other* things there are to work on, including the small ones, and buckle down and do those. Let's take those in turn. ### Filling major gaps First, on filling big gaps: There are a bunch of projects in a fairly nascent state which could make a *big* difference in how useful Rust is and how easy it is for companies to adopt it. And it's worth understanding that one of the biggest things that helps languages be more than an exciting flash in the pan is getting them used in "industry" settings. You're starting to see some of this with Rust already---companies from Dropbox to Academia.edu and many others. But for Rust to go from *niche* to *everywhere*, there are a lot of pieces of "infrastructure" that need to be built outside the language itself. *Big* infrastructure pieces. We need both the low-level infrastructure pieces like mio and the new futures library I mentioned at the top of the show, and some higher-level abstractions sitting on top of those to make it easier for people to build e.g. web services easily. {>> TODO: other gaps <<} ### Filling smaller gaps What about all the little pieces? The community actually has a good start on this. Lots of us have built little exploratory projects---another Rust binding to some C library, a part of an XML parser, etc.---and those are *great* for little learning projects, but we also need to take a lot of those and turn them into production-level tools that are at a level that can be used in larger projects. Now, don't be discouraged: if you've written that kind of small project, and you're thinking, "No way is this ready for some big company to depend on; I'm still just learning!" that's okay. No one should be sad about learning and learning in public, and no one should feel ashamed of their projects. *All* I mean is that as we move from the "just trying this out" phase to the phase where we feel reasonably competent with the language, we can start looking around and thinking about how we can turn "my first XML parser" into a *great* XML parser---perhaps by collaborating with several others who've done the same, and looking at some of the state-of-the-art options out there. Those kinds of small projects aren't that *sexy*, but they're incredibly important. In many ways, given a sufficiently decent lanaguage *foundation*, they're actually *more* important than anything else that the language might do. If you don't believe me, look at JavaScript: the language has a lot of issues in its design, and there are well-known problems with the Node.js ecosystem and tooling. I *like* JavaScript, but the amount of time I've spent chasing down something which broke five layers deep in an npm dependency is infuriating. But none of that matters that much, because there is also a vibrant community trying to solve every problem imaginable---sometimes several times over in different ways, which causes its own set of problems! And the result is that, whatever the language's warts and whatever the weaknesses of the tools, the Node.js ecosystem is flourishing. And a huge part of that is simply people's willingness to build small things which *aren't* glorious, which aren't at the very center of the community. A willingness to embrace that idea---that it doesn't have to be sexy for it to matter and be a valuable contribution---is huge. We need that in spades for Rust to become all it can. So: go write an incredible XML parser (or, better, help make one of the two that already exists more robust and capable). And then maintain it: fix bugs when they're found, keep on top of pull requests as they come in, and generally try to make it useful to people. There isn't a lot of glory in that. But it's *extremely* valuable. And you know what? A lot of Rustaceans are out there doing just that. I saw news come by this week about everything from cryptography to building Alexa skills for the Amazon Echo to a library for getting input from gamepads and controllers. This is fantastic. So, number one: keep it up. And number two: let's work to celebrate those kinds of things just as loudly as the core language itself. They're not in competition. It's the combination of the language and the things we build with it that makes this all worth doing. ## Outro -- Sponsors and Following Thanks as always to the sponsors who help make the show possible! This month, the sponsors included Chris Palmer, Daniel Collin, Eric Fulmer, Jared Smith, Raph Levien, Stephen Murawski, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes, and the top tier of sponsors on a dedicated page on the website as well. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at a variety of other services listed at the show website: newrustacean.com. There you will also find links to the news items from the top of the show, and code samples illustrating referencing and dereferencing data. You can also follow the show on Twitter \@newrustacean, or follow me there \@chriskrycho. If you enjoyed the show, please help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, sharing it online, or just telling a friend! Also, please do respond on social media, in the threads for the episode on the Rust user forum or on Reddit, or via email at hello@newrustacean.com. I love hearing from you! Until next time, happy coding! ================================================ FILE: docs/bonus-7-script.md ================================================ # Katas---learning by doing ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is *Bonus episode 7: Katas---learning by doing.* ## News and follow-up First, an apology a bit of explanation for the delay between episodes! In the last 10 days, I've traveled something like 4,800 miles for a conference and a wedding. There's are a couple of reasons I'm not at this year's RustConf or Rust Belt Rust conferences, and one of the big ones is this is too much travel! Gladly, the rest of the year is *much* slower, and things should normalize pace-wise from here. Now, a couple quick bits of news and updates: First, literally *as I record*, the first RustConf is going on! Video from the conference will be made available after the fact, and you can bet I'll be watching it. One particularly fun bit related to *this* show---as you may recall: Raph Levien is presenting on his work on the Xi editor. I'm particularly excited about that talk. Second, a couple neat things from around the community more generally: - I mentioned Claudia Doppioslash's work on gaming and Rust in a previous episode; now she and a few others have launched arewegameyet.com, which highlights the state of tools for building games in Rust. - That reminds me: if you haven't yet, take a look at areweideyet.com and arewewebyet.org to see the state of IDE support and web development respectively in Rust. Third, some updates from core: - There's a great discussion around direction and vision for the Rust language in 2017 on the Rust internals forum, which I'll link. Lots of good discussion about where and how to focus efforts to improve the language's adoption---you should read it and chime in! - Early, early, alpha-level support for incremental compilation has landed in the nightly builds of the compiler, and support for that with Cargo is being built out now---some of the long-expected fruits of MIR landing. That should help compile times a *lot*. ## Katas - I've been interested in Elm for a while (and why: ML-like, use JS at work, guarantees around it, etc.) - I've gone back to same problem in JS repeatedly - Idea isn't new to me: "katas" are a thing out there - The actual problem isn't hard, and that's a big part of what makes katas useful. The point isn't so much the problem---which you can figure out how to solve---as figuring out how to solve it *well* in *this* language. - Going back to it as you become more familiar with the language, or as you pick up new ideas lets you apply newfound knowledge while not worrying about trying to understand the *problem*. - So I did this "pizza test" with Elm. It took me a couple hours, because I was learning the language and its tooling and how the compiler works and so on - Then I started in on it it on an even broader scale with Rust. Broader how? - Elm and JS are already in-browser setups. Rust is not. - Pull in a bunch of crates: - Hyper for HTTP requests - Serde for deserializing JSON - Pencil for serving the actual rendered page - handlebars-rust for simple HTML templates - Why? To get a feel for those crates as well as for what solving *these* problems in a Rustic way feels like, just as I was sorting through it in Elm. The best ways to learn things in programming, in my experience are to *do* them, and to *teach* them. As I said in the very first episode of the show---almost a year ago, now!---that latter bit is one big reasons I'm making the podcast. It's helping *me* keep learning Rust while very busy with other things. ## Outro -- sponsors and following Thanks as always to the sponsors who help make the show possible! This month, the sponsors included Chris Palmer, Daniel Collin, Raph Levien, Stephen Murawski, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes, and the top tier of sponsors on a dedicated page on the website as well. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at a variety of other services listed at the show website: newrustacean.com, along with links to the bits I discussed on the episode. You can also follow the show on Twitter \@newrustacean, or follow me there \@chriskrycho. If you enjoyed the show, please help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, sharing it online, or just telling a friend! Also, please do respond on social media, in the threads for the episode on the Rust user forum or on Reddit, or via email at hello@newrustacean.com. I love hearing from you! Until next time, happy coding! ================================================ FILE: docs/bonus-8-script.md ================================================ # Giving Back (by Teaching) ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is *Bonus episode 8: Katas---Giving Back (by Teaching).* ## News Good news, everyone! I finished the course work for my Master's degree this past Monday, so things are settling down and it's going to be much easier to put out episodes every other week. (That last class was a weeklong intensive and was the reason this episode is reaching you a week later than usual.) Huzzah! ## Giving Back (by Teaching) Now, a few thoughts on giving back by teaching. Over the last few years, I've been working on finding ways to use the skills and abilities I have, and the advantages I've been given, to help others. There are lots of ways to do that. But one of them---and one of the ones I seem best equipped for---is *teaching*. This podcast is part of that. I haven't been in a spot where writing huge amounts of code outside of work was something I could do: I just didn't have that much spare mental energy between work and school. But writing a podcast, or a technical blog post, exercises a *completely* different part of my mind. So I've done that, and I intend to do a lot more: continuing to produce this podcast, giving well-prepared talks in my area, writing detailed technical blog posts, etc. But I've also been thinking about other, more significant ways to contribute to the world around me. In the last month, I've bumped into two other men at my church who are on the very early parts of the curve in learning programming. So I've decided to set up "office hours" for a few hours in a local coffee shop every month, and I'm going to see what I can do to help these guys get their feet under them as software developers. There are two big "rules" I'm going to have for these office hours: anyone, of whatever skill level and interested in whatever language, is welcome. That means that even though I don't *love* Java or C#, I'm going to do my very best to help these guys get up to speed on them, because that's what they want to learn---and I'm not going to say a disparaging word about either language. There's time enough to talk through the tradeoffs which come with different languages when someone has their feet under them (and, better, when they have a *job* in the field, if they want it). I've also been looking around tentatively---and, after my wife and daughters and I move to be nearer our extended family sometime in the next year, will be looking around *intently*---at ways I can actively use my background and abilities to help others "bootstrap" their way into our profession. That might be serving in a correctional facility. It might be showing up at a learn-to-use-computers class. It might be any number of things. But I have been given much, and I take seriously the idea that much is therefore expected of me. I think we *all* ought to take that idea more seriously. Accordingly I want to challenge you listeners: what are the ways *you* can help others? I have a few ideas, but I'd also love to hear more: tweet them at me @newrustacean, email me at hello@newrustacean.com, add them to the threads for the episode on Hacker News, Reddit, , and I'll mention them on the show. (If I get *enough* feedback along those lines, I'll just write another bonus episode and talk through those options!) But in the meantime, let's look at just a few of the ways you might help, regardless of where you might be in your own technical journey. And remember: you might be at different points on this curve in different skills and frameworks and language. That's how it always goes. ### Total Newbie So maybe you're just on the early side of the learning curve yourself. That's not just okay, it's *great*. You have some specific things you can offer to others both just behind you and far ahead of you---things that an experienced developer literally *cannot* offer, no matter how thoughtful. One is your *questions*. Ask them! File issues on projects you're using. If there is documentation and you can't make head or tails of it, open an issue. Be polite about it, of course, but be detailed and thorough: note what you don't understand with specific reference to the docs you're reading. Sometimes, people will just point you to materials which lay the foundation for what you're reading, and that's a win---but even there, it may suggest to them the kinds of things they might link from their own docs in a "you-need-to-know-these-things-first" way. One example of that which I really love: enough questions combined with a really thoughtful documentation team has led to the Ember.js documentation having two really helpful resources: a list of exactly those kinds of assumed foundational items, and a readily-accessible glossary of terms you might not know if you're a new developer, with links to further explanation of all of them. Those are the kinds of things it's *very* difficult for an experienced developer to identify in the specific. I might know *that* a fresh developer needs that knowledge, but I now suffer from the "curse of knowledge" and I don't remember the specifics of which pieces are confusing and how their combinations may also be confusing. So again: ask questions and open issues about confusing things! The other thing total newbies can do, which helps enormously in tackling the same "curse of knowledge" problem, is explain things to others who are just a bit behind you. If you started learning Rust a week ago and have finished your first pass through the book, you know more than someone who just discovered the language---and your new eyes can make it easier to understand exactly what they're struggling with. You can help actively with that in several ways: by writing blog posts or giving introductory talks, or just by hanging out and answering questions in places like users.rust-lang.org and Reddit, or on the IRC, Discord, Slack, Matrix, etc. Those kinds of "I just learned this thing!" blog posts can be illuminating for others just trying to dip their toes in the water---and when you get something wrong (as I did in the last episode! More on that in the future), it's a chance for *you* to learn and also a chance for the folks further down the road to improve the ways the material is taught. ### Intermediate Now, as an intermediate developer---and this is roughly where I find myself in many ways---it's sometimes murky what the best things to do are. You know enough that most day-to-day work is straightforward enough, but often not enough to tackle something like rewriting a significant library. But this is actually a great time to start investing actively in others. You *do* know enough to be productive, and that means that even if you're not an expert in a given subject, you know enough to help others get up and running. You're well-equipped to know what the common pain points in your tech stack are, and how you work around them: you have an immediate answer when someone says, "Wait, why is _foo_ not working?" because you've grown those calluses and know to simply insert a _bar_ there and move on. It's also a great spot for doing more talks and blogging to stretch your *own* knowledge. I wrote a post about a couple new features in TypeScript a few months ago, because I knew enough TypeScript and enough JavaScript that I knew I *could* figure it out. That post in turn has been illuminating to others, not least since it was one of the earlier and more thorough posts on the subject. There was nothing especially profound about what I did there; I just wrote down what I was figuring out and put it online for others to find. Now it's useful not just to me but to others. Finally, it's also a great time to be helping *write* documentation. If you spend time in the communities where people ask questions---again, the forums or chat channels---you'll see questions that come up over and over again. Find a good spot to add those to docs, or to wikis, or write a blog post explaining it both so you have an easy thing to link people to and also to help people find it by searching: not least because there are a lot of people who use any given tool but never actually make it into a forum or a chat room to ask for help. ### Expert What about the grand gurus, who know a piece of tech inside and out---the Rust core team, or people like BurntSushi, who has developed the fantastic ripgrep tool, or any number of others I could name? Well, one is writing as careful and thorough documentation as you can manage. This isn't glamorous work, and it can feel like it's taking away from your productivity. But the reality is that true *experts* in a domain can offer something besides merely their ability to accomplish the technical tasks in the domain. They can also, if they're willing to work hard at it, *develop expertise in others*. In fact, I'd go so far as to argue that the 10x-developer, usually considered mythical, *does* exist. Just not the way most people think when they talk about it. A developer who is brilliant and speedy, but who fails to pass on the knowledge he or she has gathered can accomplish an enormous amount. A developer who takes and shares her or his knowledge with others---who mentors others through their own process of developing expertise, who writes documentation so good that people new to a project can come up to speed quickly and then can accomplish something on their own---that developer can be a 10x developer *easily*. Empowering others can extend your own reach in surprising ways. It's also incredibly rewarding to watch other people go from "How does this work?" to mentoring others themselves. I've never been formally mentored in the software world, but even the informal mentoring I've had from friends and acquaintances has increased my own capabilities dramatically. That takes me to my last point for experts: step out of the way as people "level up." That's a huge part of *any* mentoring process, and it's tough for everyone, I think. But if you want people you're helping to truly succeed, you have to give them more and more responsibility with less and less support, and eventually also less and less feedback---trusting them to grow into that responsibility. Doing that can empower people *enormously*. ## Closing So there are a few thoughts on ways you can give back. There are *lots* more, of course; I've focused mostly on "teaching"---not least because that's where I'm strongest! But I'd love---*love*---to hear your ideas on other things we can do to use our abilities and time and position to help others. ## Sponsors Thanks to - Chris Palmer - Christopher Giffard - Dan Abrams - Daniel Collin - Matt Rudder - Ben Whitley - Peter Tillemans - Philipp Keller - Steven Murawski - Raph Levien - and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website, or if you're a company interested in advertising to developers, please email me! ### Info You can find show notes with links, code samples, and more at NewRustacean.com. You can follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use. And again: I'd love to hear your feedback on this topic *especially*. Until next time, happy coding... and giving back! ================================================ FILE: docs/bonus-9-script.md ================================================ # Outro Thanks to this month's $10-or-more sponsors: - Anthony Deschamps - Chris Palmer - Christopher Giffard - Behnam Esfahbod - Dan Abrams - Daniel Collin - David W. Allen - Matt Rudder - Olaf Leidinger - Peter Tillemans - Philipp Keller - Raph Levien - and Vesa Khailavirta As always, thanks as well to everyone who helps other people find the show---whether by just telling a friend, or by rating or reviewing it in iTunes or recommending it in another podcast directory, or by sharing it on social media! You can find show notes for this episode, including code samples for everything I discussed, at newrustacean.com/show_notes/e02. The show is on Twitter @newrustacean, and I am @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or – and this is my favorite – just send me an email at hello@newrustacean.com. Until next time, happy coding. ================================================ FILE: docs/cysk/bindgen-cbindgen-script.md ================================================ # CYSK: `bindgen` and `cbindgen` ## Intro Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is Crates You Should Know: bindgen and cbindgen. ## [Sponsor: Parity](https://parity.io/jobs) Before we dive in, Parity is back sponsoring the show—because they want to hire you to come work in Rust with them! Parity is advancing the state of the art in decentralized technology, and they’re using Rust to do it, leaning hard on its trifecta of performance, reliability, and productivity. They're building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Two of the larger projects they're working on are: Substrate, a framework for building blockchains, and Polkadot, a platform leveraging blockchain tech for scaling and interoperability in decentralized systems. If that sounds interesting, check out their jobs at ! ## Motivation Over the last few episodes we talked a great deal about foreign function interfaces, and I walked through how you can explicitly define and build those out yourself. However, as you can imagine, doing that for every single function and type you deal with in a large project with lots of FFI is… painful and error-prone. Happily, the work of mapping C interfaces to Rust interfaces can, by and large, be automated—with [the `bindgen` crate][bindgen source]. And, similarly, we can automate the work mapping Rust interfaces to C interfaces with [the `cbindgen` crate][cbindgen source]. Today, we’re going to dive into how each of them works! [bindgen source]: https://rust-lang.github.io/rust-bindgen/ [cbindgen source]: https://github.com/eqrion/cbindgen/ ## [`bindgen`][bindgen source] `bindgen` is an *official* Rust tool, but it is not part of the standard library. That’s because it’s not needed for *most* projects in Rust, and it’s really a library for your *build* process rather than for your crate proper. It’s a tool for *generating bindings* from Rust to C and *some* C++ libraries. If the thought of writing out bindings by hand and hoping you get them exactly right every time seemed a bit intimidating… well, you’re not alone in that; I feel much the same! bindgen only generates Rust bindings for C code. It’s designed to cover the half of the story that’s usually most important for integrating Rust into an existing codebase, where you want to be able to add Rust alongside C or C++. For example: this is exactly what Mozilla needed when they started pulling Rust into the Firefox codebase, which is pretty much *entirely* C++. `bindgen` supports two ways of using it: as a command line tool, and as a part of a `build.rs` script. The latter is the recommended path, and it gives you a great deal of control over exactly how you use it. In particular, it lets you account for architecture-specific bits dynamically—which is often important for cross-platform Rust code which is interacting with cross-platform C or C++ code! If you follow that recommendation, you don’t need separate binding files for every target you build against. However, your consumers *will* need a copy of the clang compiler to build your code in that case. Happily, it’s fairly easy to get an up-to-date version of clang on every major platform, including for multiple different Linux distros. As with build-file dependencies in general, you’ll put `bindgen` in your `[build-dependencies]` section of your `Cargo.toml` file. Then you need to create an *entry point* for the library to do its work: a single `.h` header file which uses the `#include` syntax to pull in every item declaration you need bindings for, by including *other* `.h` header files from the project you’re working with. This file has one other purpose, but we’ll come back to it in a minute. Once you have included all your requisite dependencies, you’ll go into your `build.rs` file and add a `use bindgen;` statement. Then the simplest thing you can do with its exported `Bindgen` type is create a builder and call its `header` method with the path to that `.h` file you created as its argument, and then call its `.generate` method. This will do the work of attempting to parse that header file and all the files *it* includes, and to generate a data structure which can be written as Rust type definitions of the sort we talked through in detail in episodes 029 and 031. You can write that out using the `.write_to_file` method on the generated bindings item, also just passing it a standard file path. ### Customizing bindgen There are a number of ways we can customize the behavior beyond the defaults, though, which is helpful for situations where the defaults aren’t quite what you need. #### Customizing bindgen: enums You can map C/C++ enums into Rust in a variety of different ways: - The first is as a set of constants—optionally namespaced into a module—with each Rust constant having the integer value corresponding to the enum literal value on the C side - The second is as Rust enums, with guarantees that the discriminants match across the languages. This sounds like what you always want, right? But it’s only what you always want if you’re in control of the C side, because otherwise you can cause undefined behavior with it! The docs link to an explanation of *why*; the point is that, as always with FFI, things are more complicated than they might seem at first. - The third is as bitfields, a densely packed layout designed to save space and deal with byte alignment issues—the kinds of concerns that come up when you’re dealing with registers on embedded systems, or sometimes when dealing with message protocols #### Customizing bindgen: regular types You can also extensively customize how bindgen handles different types. For one thing, you can set up a whitelist or a blacklist to determine which types get exposed in the first place. It may well be that you only want to pull in a small subset of the items defined across a bunch of different header files you’re including, but the C side doesn’t really give you that kind of control. When you `#include` a file, it’s literally just dumping the contents of that file in as a string. (I have… stories… about this behavior; if you ever happen to see me at a conference or a meetup ask me and I will happily regale you with the horrors I have seen.) You can use the `bindgen::Builder` whitelist family of methods—`whitelist_type`, `whitelist_function`, and `whitelist_var`—to tell bindgen to allow *only* a subset of items into the generated Rust definitions. You can similarly blacklist *types* from appearing with the `blacklist_type` function. However, this is only for when you need to provide your own handwritten definition of the type, because it’ll still show up in *other* functions and types, and so you have to provide a definition for the type or your crate won’t compile! In these cases, your best bet is telling bindgen to generate a type that is opaque to Rust—the inverse of the opaque type scenario I talked it great detail in e031. Here, you use the `bindgen::Builder`’s `opaque_type` helper to make it generate a type for which Rust only knows the size and alignment. You can also replace one C or C++ type with a different C or C++ type entirely entirely—one that bindgen can do the right thing with, when the original is too complicated for bindgen to get right. Servo has to do this at times with C++ types, but I’m hard-pressed to imagine it ever coming up in plain-old C code. (Of course, I could be failing to think of a weird edge case: C has a few of those!) Finally, for our purposes, you can customize what traits do and don’t get derived in *great* detail. That means you can opt out of `Copy` and `Clone`—which bindgen *tries* to do by default—or into other traits like `Debug` or `Default` or `Hash` or `Eq`, all using other methods off of `bindgen::Builder`. Now, I’ve covered this at a high level, but there are *many* more settings you can tweak and customize along the way. There are two further resources you’ll find very helpful in digging further into `bindgen`: [the official guide][bindgen guide], and the [API docs][bindgen API docs]. Give them a read (and check out the very simple example in the show notes!). [bindgen guide]: https://rust-lang.github.io/rust-bindgen/ [bindgen API docs]: https://docs.rs/bindgen ## [`cbindgen`][cbindgen source] So that does it for `bindgen`, but what about going the other direction—generating C types from Rust, say, to be consumed by Swift? For that, we’ll use `cbindgen`. `cbindgen` is *not* an official Rust tool, but that doesn’t mean you shouldn’t use it. Its design mirrors that of `bindgen`, so at a high level the *workflow* is the same as with `bindgen`, except that we’re going the other direction. `cbindgen` intentionally mirrors the API of `bindgen`. You can use it either from the command line or from a `build.rs` build script, and its API mirrors `bindgen`’s quite closely. You pull in the library, you create a `Builder`, you pass it a path to a crate directory, you call `generate` on it, and you write the fill out—but this time, instead of writing a Rust file, you’re writing out a `.h` header file. It’s worth noting, however, that `cbindgen` has some important limitations and gotachs. Specifically (and here I’m cribbing from [a blog post by one of the main authors of the crate][future-directions]: [future-directions]: https://blog.eqrion.net/future-directions-for-cbindgen/ - It has a hard time dealing with path resolution, so if you have multiple item which would resolve to the same external name, it’ll fall over - It doesn’t understand privacy modifiers, and between that and its not understanding paths, it doesn’t actually know whether something should be exported from your crate or not. That’s a big deal! It *guesses*: if an item is `pub`, it thinks it’s exported. As we talked about in detail in e030, though, that’s not correct. - Because of where it interacts with Rust code—i.e. at the level of the uncompiled syntax—it doesn’t understand macros, which are a form of code generation. There’s an option to work around this using a Rust compiler flat… but it’s not guaranteed to work properly with macro hygiene, so it’s not stable. - It similarly doesn’t always know what to do with `#[cfg]` attributes. It tries! …but it can’t always do the right thing, where by “the right thing” I mean “the thing you want” or “the thing you find unsurprising.” The net of all of those is that basically the maintainers are confronted with the problem of trying to reimplement non-trivial subsets of `rustc`! So cbindgen *does* work today, and you can use it in exactly the ways I talked through above, but you should be aware of those caveats… and you should keep your eyes on a *follow-on* project, [`rust-ffi`], which aims to address those with a more robust architecture that splits apart some of the concerns and runs as a Rust compiler plugin for the bits that need to understand Rust itself correctly. (I’m not sure how alive that project is: it was a proof of concept, but it seems promising; hopefully it gets some forward motion soon!) [`rust-ffi`]: https://github.com/eqrion/rust-ffi ## Binding libraries for other languages The other thing worth calling out here is that there are dedicated libraries for providing Rust bindings for most of the major scripting languages. I’ll name them here, and link them in the show notes—in many cases, those are *the* place you should start if you’re wanting to augment code written one of those languages with a native extension in Rust. - Python has [PyO3](https://github.com/PyO3/PyO3) - Elixir and Erlang have [Rustler](https://github.com/rusterlium/rustler) - JavaScript has [Neon](https://neon-bindings.com) - Ruby has [Helix](https://github.com/tildeio/helix) Those are in various degrees of maturity and stability, but all are at least *usable* and indeed all of them are actually being used in production. There was [a great write-up from the folks at Discord][discord-elixir-rust] just today (as I write and record) about how they’re using Rustler to speed up a critical part of their Elixir back end (linked in the show notes, of course!). [discord-elixir-rust]: https://blog.discordapp.com/using-rust-to-scale-elixir-for-11-million-concurrent-users-c6f19fc029d3 ## Testing The last thing to say is that *you should test your bindings*. It’s one thing to look at code and be pretty sure you wrote the right things. It’s something else entirely to have tests in place that make *sure* you do. Use Rust’s built-in testing infrastructure to check on a couple things: 1. Do a simple “is this just basically right?” test. Does invoking each function you’re importing via FFI give you the right results in the happy path? Testing *more* than the happy path is probably good, but at a *minimum* you want to check this part. 2. Do you end up with any panics because you have invalid data flowing across the FFI boundary? To manage this you may need to write some unsafe code; but it’s a good way to make sure that your invariant-checking pieces are correct. Assert that things *should* panic when given bad data, for example, using the `#[should_panic]` attribute on a test function. Or get more fine-grained using the `std::panic::catch_unwind` function to get a `Result` with the error and dig into its details. I expect this is a place where some kind of fuzz- or property-based-testing could also be useful… but I’ll freely admit that that’s just speculation, because I haven’t ever actually been able to give those a whirl myself. I’d love to hear if you’ve put those kinds of tools to use in FFI contexts in particular! ## Conclusion Thanks as always to this month’s $10-or-more sponsors: - Raph Levien - Martin Heuschober - Graham Wihlidal - Jason Bowen - Soren Bramer Schmidt - Daniel Collin - Peter Tillemans - Oluseyi Sonaiya - Behnam Esfahbod - Nicolas Pochet - Jonathan Knapp - Dominic Cooney - Cristian Paul - Dan Abrams - Nathan Sculli - James Hagans II - Chip - Anthony Deschamps - Andrew Dirksen - Embark Studios - Paul Naranja - Ryan Osial - Benjamin Manns - Michael Mc Donnell - Daniel Mason - Bryan Stitt - Alexander Payne - Nick Gideo - David Carroll - Daniel Bornkessel (April only) - John Rudnick - Rob Tsuk - Nick Stevens - Arun Kulshreshtha - Adam Green - Jako Danar - Jeff May - Zach Peters - Scott Moeller - Evan Stoll - Joseph Schrag - Matt Rudder - Ramon Buckland - Johan Andersson - Brian McCallister - Jerome Froelich - Ola Fadeyi You can find show notes for this episode and every other at —with scripts, code samples, and a number of interview transcripts. Please recommend the show to others if you like it, whether in person, via your podcast directory, or in various media online! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending men an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/cysk/serde.md ================================================ # Crates You Should Know: Serde Hello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust programming language and the people who use it. This is **Crates You Should Know: Serde.** ## Intro It’s actually kind of amazing to me that we’re two and a half years into the show before I finally get around to talking about Serde. It’s been mentioned on the show repeatedly, and it’s one of the absolute core building blocks of the Rust ecosystem, and it’s frankly just a really impressive piece of software in its own right – inside the Rust ecosystem *or* outside. So now we’re going to do a solid dive into the library’s purpose, approach, and (at a high level) APIs! ## Serde Serde is a library for *serialization* and *deserialization* of data – data of all sorts. The name is just a mashup of the first syllable of *serialization* and *deserialization* - ‘s’ ‘e’ ‘r’ from serialization and ‘d’ ‘e’ from deserialization. One thing that distinguishes Serde from e.g. the JSON-to-data-structure implementation in your other favorite language is that *most* of the time, the serialization and deserialization that happens, and really the data layer transformations of any sort (including for ORMs) are done at *runtime*, by mapping over the supplied data structure. Serde and Rust obviously still have to do some work at runtime, but that work is a lot narrower in scope, because they use Rust’s types and Serde’s traits to avoid any runtime attribute tagging or reflection. As is often the case with this kind of trait-driven programming, the compiler can often optimize it down to the same kind of performance you’d get by hand-writing a serializer... but as we’ll cover in a moment, you pretty much never have to hand-write serializers! The current list of supported formats for serialization and deserialization is pretty long! Among others, you can serialize and/or deserialize to JSON, YAML, MessagePack, TOML, Pickle (from Python), URL, and XML. (And there are more!) ### Using Serde as a consumer Serde, as you might expect, leans heavily on a few core traits: `Serialize` and `Deserialize`. And, happily, these are traits you’ll only *very* rarely need to implement yourself. Courtesy of Rust’s support for *custom derives*—which Sean Griffin and I talked about a bit in [our discussion of Diesel 1.0](https://www.newrustacean.com/show_notes/interview/diesel_1_0/part_1/index.html "Diesel 1.0, Part 1"). For Serde, you can take *essentially* any data type you can define in Rust and simply use the `derive` attribute by writing `#[derive(Serialize, Deserializer)]` in front of any type you define. In a few rare occasions, you’ll need to write the implementations yourself (and the really excellent docs have you covered in that case), but usually you’ll just derive these traits automatically. To make that work, you’ll need to make a couple tweaks to your project besides adding Serde itself to the dependency list. 1. Add `serde_derive` to your Cargo.toml. It’s an *optional* dependency of Serde—and it’s probably safe to say it’s *usually* installed alongside it! But if you happen to be in a scenario where you’re not going to be using the derives, you don’t have to install it. 2. Add the dependencies for the target format you want to use—again, Serde breaks out its support for each format into its own crate. This keeps your build size down: there’s no reason to include, say, `serde_yaml` if you’re only targeting JSON. 3. In your `main.rs` or `lib.rs` file—depending on whether you’re building an application or a library—add the top-level attribute to include the custom derive macro: `#[macro_use] extern crate serde_derive`. And that’s it! You can now derive `Serialize`, `Deserialize`, or both on any `struct` or `enum` you need to serializer or deserialize. Once you’ve set up a data type with the relevant attributes, you can serialize and deserialize them by using the main functions a Serde target library supplies. The most common ones are: - `ser::to_string`: the function for serializing a given Rust item into a string of a given format - `de::from_string`: the function for deserializing a string of a given format into a Rust item For other target formats, you’d see different names—if the Serde library you were using targeted binary buffers, for example, it would be `ser::to_bytes` and `de::from_bytes`. Once you have the basic configuration all set up, you can start *using* those functions with your types. You can also further customize the way a data type is serialized and deserialized by using other *attributes*. Serde has attributes for customizing the container (the struct or enum itself); customizing enum variants; and customizing struct fields. For example, you can rename a struct field or enum variant. These kinds of things might come in handy when you’re translating between the expectations from different data layers in other languages, for example. In JavaScript, it’s normal for payloads to be formatted in `camelCase`—lowercase first letter, capitalized first letter of all words following in a name—but since it’s normal for Rust fields to be `snake_case`—all lowercase, separating words in a name with underscores—you can use Serde’s `rename_all` container attribute. You can also skip fields and variants entirely, or define custom functions to serialize and deserialize them. In short, Serde has *really* good defaults but also the flexibility to do most of what you need via attributes if the defaults don’t match your specific scenario... and the ability to just write your own specific `Serialize` and `Deserialize` implementation yourself if even *those* don’t get you far enough. ### Using Serde as a producer The other use case for Serde is creating support for a new source for deserialization and target for serialization. As I noted earlier, Serde already supports a wide array of target formats. However, there are cases where you might need to write your own format for a given data representation type, or for a given protocol for transmission. In that case, you can implement your own serializer and deserializer plugin library, just like the existing libraries like `serde_json`. Serde—as its docs emphasize!—is not a *parsing* library. Its functionality is *specifically* for converting data to or from a given, *already-parsed* format and Rust data structures. So, for example, `serde_json` [parses the JSON itself](https://github.com/serde-rs/json/blob/master/src/de.rs#L110), iterating through a buffer of bytes, and likewise actually [generates the JSON itself](https://github.com/serde-rs/json/blob/master/src/ser.rs#L72) (including supplying a variety of options for how you print the JSON). The API you have to implement is not *large*, and it is *well-documented*. For any given data type, you have to implement the `Serialize` and/or `Deserialize` traits (depending on what you’re doing), and conventionally you should also supply `to_` and/or `from_` functions, like `to_str` and `from_str` for serializing and deserializing `&str` string buffers, or `to_bytes` and `from_bytes` for serializing and deserializing directly to `&[u8]` bytes buffers. I’m not going to try to talk through everything involved in writing your own implementation; that would quickly involve far too much trying to describe code aloud, and I do enough of that in this podcast! Instead, if you’re interested in seeing a really quite straightforward and relatively easy to understand example, I recommend blocking out a couple hours and reading through the `serde_json` implementation. You’ll probably learn a lot! ## Outro So that’s Serde! If you need to serialize or deserialize stuff in Rust… this is where it’s at! ### Sponsors Thanks, as always, to all of this month's sponsors. Contributors who gave at least $10 included: - Aaron Turon - Alexander Payne - Anthony Deschamps - Chris Palmer - Behnam Esfahbod - Dan Abrams - Daniel Collin - David W. Allen - Hans Fjällemark - John Rudnick - Matt Rudder - Nathan Sculli - Nick Stevens - Peter Tillemans - Olaf Leidinger - Oluseyi Sonaiya - Raph Levien - and Vesa Khailavirta If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for *this* episode at . If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/cysk/wasm.md ================================================ # Crates You Should Know: the `wasm-` tools Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is Crates You Should Know: the `wasm-` tools. ## `wasm` ### Background First, a little background on WebAssembly, or “wasm”. I’ve mentioned it in a number of contexts on the show before, but I’ve not dug into the details at all. WebAssembly is the direct descendant of a research effort called asm.js, which was an attempt to specify a subset of JavaScript that would work as a compile target for C or C++, specifically to allow games to run in web browsers. The aims of and possible uses for WebAssembly are much broader than just games though: it can be used for all sorts of performance-intensive applications, running as a complement to (rather than a replacement for) JavaScript in the browser. ### How it works So how does that work in a technical sense? WebAssembly is a binary instruction format for a stack-based virtual machine. Because it’s a low-level binary format, it can in principle run at native speeds – “in principle” because it does depend on the context it’s running in, of course. This low-level format serves a compile target for higher-level languages, where by higher-level I mostly mean “like C++ or Rust” rather than “like Ruby or Elm.” WebAssembly can be run in all modern web browsers, and it can actually be implemented in existing JavaScript VMs. However, it is not *limited* to running in browsers or JavaScript VMs, and you definitely won’t see native performance if it’s implemented in an existing VM rather than having its own dedicated runtime. And it’s worth reiterating: the browser is just the first and currently-most-popular deployment target. I’ve already seen research on running it as kernel code – and to be clear, I mean as *normal*, Ring 0 kernel code, with neither a browser nor a JavaScript VM anywhere to be seen. There are possibly real long-term benefits to doing exactly that, too, though I’m not going to dig into them today. But let’s step back and unpack that description a little bit. - wasm is a *binary instruction format*. This is basically the same as other kinds of assembly languages, which are *instruction formats* as well. It’s a binary format for speed reasons: no parse-the-string-into-the-actual-instructions step required. However, there *is* a human-readable format, which is handy for understanding the output of your compiled code. - wasm is designed for a *stack-based virtual machine*. There are a variety of kinds of virtual machines in the world, and most of them you’re like to be familiar with (Java, C♯, Python, Ruby, JavaScript, etc.) have both a stack and a heap, along with garbage collection. The wasm virtual machine model does *not* have a heap, and it does *not* have garbage collection. This has a lot of implications for the programming model, which, again, I’m not going to dig into today. It’s enough for now to know that the constraints exist so you can have them in mind if or when you start actually implementing things in wasm! It is important that I note that WebAssembly does have an explicit goal of being a viable compile target for languages which *do* have VMs in the future, but also chose initially to target languages with low-level memory models: C, C++, and Rust are the major source languages which target WebAssembly today. There are early experiments happening in other languages, too, but large-scale real-world application of those is probably a year or more away. And we’re here for the Rust side anyway, so let’s talk about how you’d actually go about targeting and using wasm with Rust today. Because you can, and it’s actually not all that hard! ## Using wasm The first thing you should do is add the target, so you can compile to WebAssembly *at all*: run `rustup target add wasm32-unknown-unknown --toolchain nightly`. The name of the target triple tells you that you don’t know the architecture or the OS it’s running against; you know only the instruction set to use (in this case, `wasm` instead of say `i686` or `x86_64` or some such). You can then manually run the compiler with the `wasm32-unknown-unknown` target specified, and you’ll see output in `target/wasm32-unknown-unknown`—with a `.wasm` extension instead of the usual binary. Then you’d need to pull that into your existing JavaScript environment with the right host bindings. In other words, you’ll need to basically write some JavaScript by hand to get everything doing exactly what we want and need to *use* this WebAssembly code. So, it’s nice that we can actually build wasm! But clearly this isn’t especially useful output. We need some help from the crates ecosystem to be *productive* with it. And that takes us into the actual *crates you should know* for dealing with wasm. ### `wasm-bindgen` The first crate you should know about is `wasm-bindgen`. If you’ve heard of the `bindgen` tool, this is like that, but for `wasm`. If you *haven’t* heard of the `bindgen` tool, it’s pretty much the C and C++ equivalent of what I’m about to describe for JavaScript. WebAssembly itself only supports a very limited set of types: basically, short and long integers, and short and long floating points. The other “types” in the language are just functions or particular layouts of these kinds of types. But of course, in both Rust and JavaScript, we are essentially *always* dealing with types much more complicated than just integers or floats. `wasm-bindgen` does the work of generating mappings between WebAssembly and JavaScript that let you do things like pass a Rust string to JavaScript or deal with JavaScript exceptions in Rust. Without that, you’d need to write a ton of manual glue code—specifically, manual glue code in JavaScript that uses integers for pointer arithmetic and for indexes into reference types. That is not a lot of fun. Instead of writing all of that code by hand—an error-prone process if ever there was one—you use `wasm-bindgen`: 1. Add it to your crate as a dependency. 2. Install the `wasm-bindgen-cli` tool. 3. Annotate both any `extern` JS items you want to use and also any Rust items you want to export with the `#[wasm_bindgen]` attribute. (You’ll also need to enable the `proc_macro`, `wasm_custom_section`, and `wasm_import_module` features at the top of your crate for this to work. That means a nightly version of the compiler: all of this stuff will eventually stabilize but right now we’re just figuring it all out!) 4. Compile your crate with the `wasm32-unknown-unknown` target, again using the nightly compiler. This will generate `target/wasm32-unknown-unknown/the_name_of_your_crate.wasm`. 5. Run `wasm-bindgen` on that output; you can specify the directory where you want the output. Now you’ll have a `the_name_of_your_crate.js` wherever you specified. ### `wasm-pack` So it’s great that we can compile down to WebAssembly, but we’re still left with a pretty important question. How do we get that to the environment we’re consuming it from – *especially* in a way that means other consumers don’t have to worry about the fact that it’s Rust? After all, one of the things we want to be able to do is ship WebAssembly so that *anyone* can use it. If we’ve written some super speedy Rust/WebAssembly implementation that we want JavaScript consumers to be able to use easily, we want to make sure they *don’t* need to install Rust and understand *its* ecosystem. Wasm should just be wasm from their point of view. Enter the `wasm-pack` tool! It’s a command line tool that actually abstracts right over `wasm-bindgen` and all the invocations we just talked through and builds a package that’s ready to ship to npm *for you*. I talked through `wasm-bindgen` first because I think it’s important to understand what’s going on under the hood, and because you still need to do everything but the last step of running `wasm-bindgen` directly on your code. You replace that step by running `cargo install wasm-pack` and then running `wasm-pack` in the root of your crate, or somewhere else with the path to your crate as an argument. Then it runs `wasm-bindgen` for you on your compiled artifacts. The result will be a compiled directory called `pkg`, with a `.wasm` file and a `.js` file which consumes it, alongside a `package.json` all set up and ready to ship to the npm registry. You can publish that to npm as long as you have Node and either the `npm` or `yarn` command line client installed! Then any consumer which understands WebAssembly—Node 8 or later, as well as an increasing number of bundlers like Webpack and all evergreen browsers—can run your WebAssembly! ## Closing So that’s where things stand *today*. As I noted at the outset, this area of the ecosystem is moving incredibly quickly right now, so you should keep your eye on the updates from the wasm working group and watch these repositories. As neat as things already are here, they’re going to be a lot better by the end of the year! Thanks to everyone who sponsors the show. This month’s $10-or-more sponsors included: - Aaron Turon - Alexander Payne - Anthony Deschamps - Chris Palmer - Behnam Esfahbod - Dan Abrams - Daniel Collin - David W. Allen - Derek Buckley - Hans Fjällemark - John Rudnick - Matt Rudder - Marshall Clyburn - Nathan Sculli - Nick Stevens - Peter Tillemans - Paul Naranja - Olaf Leidinger - Oluseyi Sonaiya - Ramon Buckland - Raph Levien - Vesa Khailavirta - and Zachary Snyder If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for _this_ episode at . If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/cysk-1.md ================================================ # `quick-xml` ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Crates You Should Know: `quick-xml`*. ## The crate As part of my work on my Lightning static site generator, I realized I needed to be able to quickly parse XML for syntax highlighting: I want to be able to do that at build time, rather than running JavaScript on the page when a user sees it. (I'll talk about the crate I'm using to do *that* in a future crates-you-should-know episode!) The challenge I faced was taking a bunch of well-formed HTML and reliably identifying every language-tagged code block, extracting it, syntax-highlighting it, and then replacing it in the original content. As you know if you've ever tried to do this kind of thing in HTML or XML, you *might* be able to get away with handling this with a regular expression *most* of the time, but eventually that approach will blow up in your face. This is a job for an XML parser and writer! (HTML is roughly a subset of XML. It's not strictly a subset, but usually you'll find that XML parsers can also handle HTML.) So I went looking for an XML crate! There are a number of XML-processing crates in the Rust ecosystem presently, and I read through the docs for each of them and played with a couple of them. I landed on `quick-xml`: it's fast, it has a fairly ergonomic API, and it supports XML namespaces. (If you're wondering, I don't need namespaces for *this* project, but lightning is not just about static site generation for me; it's also a proving ground for a bunch of *other* ideas I'm working on.) So let's talk about that API a little! The crate is pretty straightforward. At the top level, it exposes four structs and one enum: `Element`, `XmlDecl`, `XmlReader`, and `XmlWriter`. There are also some types for handling attributes, errors, and namespace management, off in their own dedicated modules. The `Element` type is the workhorse of the struct types, and the reader and writer types and methods use it heavily in conjunction with the `Event` enum. The `Event`s are things like start tags, end tags, comments, text, and so on---each variant contains an `Element`. `XmlDecl` is just a wrapper around an `Element` with some extra functions for handling the specific attributes you care about from XML declarations specifically. The `XmlReader` and `XmlWriter` types do exactly what they say: give you an interface for reading and writing XML. Now, `quick-xml` is implemented as a "pull parser," meaning that instead of preemptively handing you a fully parsed tree or something along those lines, it works as an iterator, which in turn allows you to step through it as you will. There are upsides and downsides to this approach. The biggest downside is that if you want a tree structure, you have to build it yourself. The biggest upside is that if you *don't* need a tree structure, you don't pay the cost of having it anyway. That's particular interesting for memory usage reasons. I'm not *overly* worried about that in the case of Lightning---it should be a memory hog---but I also take the view that if you *can* do things in a more lightweight fashion, it's often good to do so. That's a big part of what attracts me to Rust, in fact: the ability to do things that are fast and lightweight on a user's machine. In any case, the net result of making `quick-xml` be a pull parser is that parsing and writing some XML with the crate was pretty easy. Here's how it works: The `XmlReader` takes a buffer of content and produces a stream of `Event`s, and the `XmlWriter` takes `Event`s and writes them to anything which implements the `std::io:Write` trait. In practice, that means that you can just treat the reader type like a standard iterable---because it *is* a standard iterable. When I talked about traits back in episode 9, I hinted at this kind of thing, with `std::iter::Iterator` specifically. Here's where all that power comes to bear: you can use the exact same set of iteration methods on an `XmlReader` as you can the built-in `Vec` type. Then, to do whatever transformations you need to do, you can just match on the `Event` type. In Lightning, that translated to pulling the events out of the `XmlReader` instance, inspecting them to see if they were important for syntax highlighting (and doing the syntax highlighting if so), and then pushing them into an `XmlWriter` instance. To do this, I built a little state machine which determined what to do from each event coming out of the reader. If the event wasn't of interest for syntax highlighting, I'd just push it directly into an `XmlWriter`. If the events matched the magical pair of tags---`pre` and `code` with a language class attached---I could grab the *text* element, parse it, and hand it back, building a new `Element` out of the highlighted code. Then I could push *that* into the `XmlWriter`. And when I'd finished processing the whole thing, I could just convert it back into a string for further processing or write it to a file. I've used very powerful XML parsing toolchains before; in particular I made heavy use out of the Python lxml tool a couple years ago when generating the HTML for HolyBible.com. Certainly if you wanted to do the kinds of things that gives you, you'd need to build on top of `quick-xml`. But, and this is important, you *can*. It's a great little library, with a very well-thought-out API. If you're working with XML or HTML, this is well worth becoming acquainted with. And if you haven't used a pull parser before, this is a great place to learn it. *I* hadn't ever done so, and I learned a ton from the experience. In fact, sometime in the next year or so, I end up implementing a parser in Rust, it will almost certainly be a pull parser. More on that when it happens. ## Closing In short, if you're doing things with XML, `quick-xml` is a great bet---and it's also open to contributions, so if you find something it doesn't do well, you should file an issue or open a PR! ### Sponsors Thanks to - Chris Palmer - Matt Rudder - Ben Whitley - Peter Tillemans - Philipp Keller - Steven Murawski - Raph Levien - and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website. ### Follow You can also find links to the docs, repository, and crate page for `quick-xml` at NewRustacean.com. You can follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use. I hope you've enjoyed this first crates-you-should-know episode, and I hope to put out at least one of these a month. I have a handful on my list, but I'd love to hear suggestions for more. You can shoot those my way, or respond more generally, in the threads for the episode on the Rust user forum or Hacker News, or by emailing me at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/cysk-2.md ================================================ # `clap` Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 show about learning the Rust programming language. This is *Crates You Should Know: `clap`*. ## The crate ### Background When I started building Lightning, I knew that part of what I would need would be a really great command line interface, and that it would need to be robust enough to handle not just generating a site but also rapidly creating posts, pages, etc. In my previous setup, I'd actually created a custom tool to do all of those things, and other site generators (like Jekyll) include this functionality. In Rust, you have three major options for handling this kind of thing. 1. You can just directly access the arguments handed to the process, using the `std::env::args` function, which hands you back an iterable struct of the arguments. 2. You can use `docopt`, a Rust implementation of the docopt command line interface language (from Python), by the same guy who built the Rust regex library and the `ripgrep` Rust grep tool. It's a great tool, and I might come back to it at some point in the future. 3. You can use `clap`: a *command-line-argument-parser* (where the name is an acronym from the description: c-l-a-p). This is our focus for today, and it's *very* different from `docopt` in a lot of ways. I don't recommend using the args directly unless perhaps for a very small toy bit of code. Using `docopt` or `clap` is a much better choice: both give you help messages essentially for "free" once you've done the work of setting up the structure. Both can also give you basic shell completion for bash, and clap can generate completions for zsh, fish, and PowerShell as well. You also get a lot of mileage out of community-tested and -embraced tools. One other qualification before I dive into talking about `clap`: I picked it not because I think it's *better* than `docopt`, but because it was the one that meshed best with how I like to approach this problem, and so was the one I started using with Lightning. ### The API The usage pattern for `clap` is straightforward: you define a configuration it should use, and at runtime it parses the args wherever in your program flow you take that configured struct and run the handy `get_matches()` method. Usually, that's right at startup, of course. `get_matches()` takes the arguments passed to the program and converts them into a data structure you can readily convert into whatever *internal* data structures you need for running your program. There are three major ways to configure `clap`. First, you can use a normal (and quite elegant) Rust API to build it directly inline. This is the tack I took initially with Lightning, because it was the most familiar to me after having used Python's `argparse` library in the past. And in fact, in many ways `clap` feels like a spiritual successor to that library, so if you've used it and like it, you'll appreciate `clap` a lot---not least for the ways it *improves* on that earlier model. In this mode, you get to use the *builder* pattern, a concept I may have mentioned before but which I now realize deserves its own full episode. From a user's perspective, though, you just create an instance of the type by writing `clap::App::new()` and then supplying further calls on that instance. The methods are set up so that you can just chain the calls one after another---you don't have to set up any intermediate variables. Other methods include things like `arg`, `subcommand`, `version`, `author`, `about`, and so on. There are also the `Arg` and `Subcommand` structs, along with several other helper structs. `Subcommand` instances are just more `App` instances, but attached to a parent `App`, so they have all the same customizability and capabilities as the main `App`. `Arg` instances let you specify the name (and a short variant) of the argument, whether it's optional or required, whether it's positional, help text for the argument, even things like whether the argument is required *unless some other condition* holds. They're basically as configurable as you could want. You can also group `Arg`s with `ArgGroup`s. Second, you can write a YAML file specifying the various options and their relationships. These give you a *subset* of the capabilities you have in the full library API. Mind: it's an extremely full-featured subset. Though I started off with the Rust API for Lightning, I ended up switching over to the YAML version because it does everything *I* need. (Note that the YAML version is behind a feature option in Cargo---another thing I'm pretty sure I haven't covered, but which should probably get its own short episode.) I'll link both my Lightning code and, more importantly, the example in the `clap` codebase, which covers *all* the features the YAML variant supports. Third, you can use a macro, `clap_app!`, which gives you a handy short-hand syntax which sits somewhere between the YAML and the library API in terms of ergonomics. It's definitely briefer than the full API to use, and looks closer to the kinds of things you'd write in the YAML form. It will, by dint of being a macro, be much more difficult to see where you got things wrong if you mess up, compared to the full library API. I should also add here that there are a bunch of other convenience macros you can use to get information about the crate at compile-time even in the standard API approach---tools like `crate_authors!`, `crate_description!`, and `crate_name!`, which give you, well, the crate authors, description, and name respectively. Those let you keep the name, description, and author fields of your help output in sync with what's in your crate automatically. Don't-repeat-yourself and all that jazz! One other thing I want to say about `clap`: its documentation is simply superb. The index of the automatically generated docs includes a lengthy example of how to use the library in each of the three ways mentioned above. There are also multiple examples of using the app in the `examples` directory in the repository, which I believe combine to cover every feature the library has. I had a question at one point about something I didn't perfectly understand from the documentation, so I went and looked and exactly that case was covered by one of the examples; it solved my question entirely. That was a *fabulous* experience, and I wish more libraries did it. It's a big inspiration for me, in fact: I won't be calling Lightning "1.0" until I have that same degree of coverage in docs. There's even a work-in-progress online *book* on creating command-line applications, using clap. Note: when I say "work-in-progress" I mean it: the site itself describes the material as "pre-alpha" and many of the chapters don't yet exist. Still: there's a lot of great material here. ## Closing In short, `clap` is a *fantastic* utility library for building command line tools, and it's well worth your time! It's also actively developed, in the open on GitHub, so you can and should contribute if you find a gap or a bug! ### Sponsors Thanks to - Chris Palmer - Christopher Giffard - Matt Rudder - Ben Whitley - Peter Tillemans - Philipp Keller - Steven Murawski - Raph Levien - and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website, or if you're a company interested in advertising to developers, please email me! ### Info You can also find links to the docs, repository, and crate page for `clap` at NewRustacean.com. You can follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use. I'd love to hear your feedback, as well as suggestions for topics, interviewees, and so on, in the threads for the episode on the Rust user forum or Hacker News. I also love getting email---you can send me a note at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/cysk-3.md ================================================ # RLS Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 show about learning the Rust programming language. This is *Crates You Should Know: R.L.S.* ## The crate In terms of *exciting* things happening in the Rust ecosystem right now, there are a lot we could mention – not least crates like Diesel and Rocket which are especially appealing to me as a web developer. And we'll get around to a bunch of those eventually. But today, the crate I want to talk about is one you're not very likely *ever* to use by adding it to your `crates.toml` file, but which by the end of 2018 you will probably be using in every single Rust project nonetheless: the Rust Language Service (or RLS for short). The RLS is Rust's answer to the question: _How do we make it easy for everyone to have a great integrated development environment for Rust?_ For the most part, IDEs for other languages have always had to implement their own smarts about the language. So, for example, the JetBrains family of IDEs – tools like IntelliJ IDEA, WebStorm, PyCharm, RubyMine, CLion, etc. – all use some common underlying infrastructure for things like code analysis, completion, refactorings, and so on. That infrastructure is shared among JetBrains products, but they have to implement everything specific to Java, Scala, JavaScript, Python, PHP, C++, etc. for themselves. And if you open up Eclipse, it has its own infrastructure for code completion, refactoring, etc. Lighter-weight GUI text editors like Atom, Visual Studio Code, and Sublime Text have *their* own code completion And if you're running vim or emacs, they have their own tools, too. Every editor has to reimplement the same things. But not so with Rust. The Rust Language Service means every editor which supports the open-source *Language Service Protocol*, can have completion, type inference, type checking, and (soon-ish) automated refactoring and code formatting tools for Rust… basically for free. ### Background: LSP A few years ago, as part of its work on Visual Studio Code and the plugins it developed for supporting cross-platform .NET work in C#, Microsoft developed the *Language Service Protocol*. The protocol defines a standard way for a *client* (normally, though not *necessarily*) an editor of some sort to talk to a *server* (e.g. a compiler or other language analysis tool). The protocol defines the kinds of messages, the format they go in, etc. in a straightforward JSON format. And because it's such a straightforward format, you can talk to a LSP server via simple command-line call if you want – which makes it fairly easy to test at a basic level, and even (in principle) lets you do interesting things like build Read-Evaluate-Print-Loops (REPLs) with it. (There's nothing like that on the radar for Rust, at least to the best of my knowledge, but it's certainly interesting!) I use the TypeScript Language Service every day at work, and it means that editors like VS Code, Sublime, and Atom all have pretty similar feature sets and behavior for doing TypeScript development, despite being very different editors in many other ways. It brings the experience of writing TypeScript in those languages – with community-supported plugins, in the cases of Atom and Sublime – very nearly to parity to the professionally developed and supported features of JetBrains IDEs, and even the official Microsoft support VS Code plugin... is just a TypeScript language server client. ### Status If you listened to the second news episode, you'll recall that I mentioned this was coming down the line and was in a very early and very rough "alpha" stage back in late 2016. As of this week (in mid-April, 2017), it has graduated from the "early alpha" stage it was in then to "beta": you can get it with nightly builds of Rust *today* by doing `rustup update nightly` and then `rustup component add rls`, `rustup component add rust-analysis` and `rustup component add rust-src`. Even better, editor plugins can (at least in theory) do all of this *for* you, just by asking permission to run `rustup` for you. The best ways to use this today are either to follow the instructions with the reference VS Code client from the official repository, or to use Kalita Alexey's `vscode-rust` VS Code extension – an actively-developed fork of the older and now unmaintained RustyCode extension. (I'll link that in the show notes, of course!) ### The Future There's a lot that works well now, but there is also a lot of room for further improvement with the Rust Language Service. First, and most painful to me: there are no automated refactorings yet, even the simple ones like renaming. The combination of find-and-replace plus a reliable compiler takes you a long way on that, to be sure: it's worlds better than the story in JavaScript, for example. But being able to hit a keyboard shortcut and rename a function or a type or even just a local variable and have it work everywhere it needs to throughout your whole codebase is a big win. When you've gotten used to being able to do that, going back to not having it feels barbaric. The same is true of extracting chunks of code into their own functions. You don't always know exactly where things will break down into discrete transformations; good refactoring tools let you do it on the fly as you as you identify common things to reuse while working through a given set of functionality. Speaking from experience, that is an incredible productivity boost. ...and the RLS isn't there yet. However, renames are behind a feature flag, and although further refactoring is still just a twinkle in Nick Cameron and Jonathan Turner's eyes, there's hope. In part, that's because of the other thing that isn't there yet: further improvements to the compiler itself to support the RLS. Some of the initial requirements (like incremental compilation in general) have just started making their way toward beta and stable builds. Others are further off: getting data on demand and incrementally for just the very specific local pieces of the code base. (And those kinds of changes could ripple out to have powerful effects elsewhere in the Rust development cycle: it's not hard to imagine how they could not only be helpful for compilation speed but also for REPL-like interactive programming approaches.) ## Closing So that's the Rust Language Service in a nutshell. It's already making my life far more awesome when writing Rust, and I am excited to see where it goes over the next year. If you enjoyed hearing a bit about the RLS today and want to hear more... you're in luck! Coming up next is an interview with Jonathan Turner, who helped build first the ### Sponsors Thanks to - Anthony Deschamps - Christopher Giffard - Chris Palmer - Dan Abrams - Daniel Collin - Matt Rudder - Ben Whitley - Peter Tillemans - Philipp Keller - Raph Levien - and Vesa Khailavirta If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website, or if you're a company interested in advertising to developers, get in touch! ### Info You can also find show notes and links for this episode and previous episodes, code samples, and more at NewRustacean.com. You can follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use. I'd love to hear your feedback, as well as suggestions for topics, interviewees, and so on, in the threads for the episode on the Rust user forum or Hacker News. I also love getting email---you can send me a note at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/cysk-rayon.md ================================================ # Rayon #podcasts/new rustacean/crates you should know# ## Intro Hello, my name is Chris Krycho, and this is the New Rustacean podcast – a show about learning the Rust programming language. This is Crates You Should Know: Rayon. ## Overview One of the major promises of Rust is that it can do "threads without data races." For anyone who's ever done multithreaded work in most conventional languages, that sounds almost too good to be true. The only approaches which have proven capable of solving this is Erlang's functiona, fail-fast model; and trying really, really hard to be really, really careful. As usual, that "be really, really careful" approach tends not to work out all that well in practice: as hard as you try, inevitably you end up with two different threads trying to access shared memory at the same time and things go badly. One solution to this problem in other contexts has been pure functional programming, leaning on persistent data structure implementations to make the approach ergonomic and workable. But it's difficult to apply those solutions in the high-performance, deterministic contexts many Rust users need. As usual, Rust's approach to ownership gives us superpowers, and Rayon makes those superpowers easy to use for everyone. ## Using Rayon Rayon's API is actually two distinct APIs, which you'll choose between depending on what exactly you're doing. Following the crate itself, I'll describe these as the "parallel iterators" API and the `join` API. Actually using Rayon is, as we’ll see, quite straightforward. ### The parallel iterators API The parallel iterators API is incredibly straightforward to use if you're used to working with Rust's iterator APIs at all, because, well... it's *basically* the same API, with just one important modification! You use one of the new trait methods, `par_iter` and `par_iter_mut`, to take an existing type which can be converted to an iterator and convert it to a *parallel* iterator instead. As is conventional in Rust, the `_mut` suffix on the default name gets you a *mutable*, parallel iterator instead of the default immutable parallel iterator. Given my constant use of the words "parallel iterator" in the last few sentences there, it's probably no surprise that Rayon's main trait is called (wait for it) `ParallelIterator`. It provides most of the same functions as you'd find on `std::iter::Iterator`. There are a few that aren't there in Rayon's `ParallelIterator` trait, because they don't map across correctly -- for example, the `next` method is pretty weird to think about in the context of a parallel vs. sequential iterator. In a sequential iterator, it's always clear what the "next" item is; in the parallel case, by definition, the "next" item depends on which thread is asking, and has no definite meaning in the context of defining, say, something you've `map`-ed over in a parallel way. `ParallelIterator` also provides a few things that the native iterators *don't* provide—most notably, `for_each` and `for_each_with`, which are basically methods designed to do side-effecting operations (unlike `map` or `map_with`, which are designed to be pure, i.e. to have no side effects). ### Prelude There are a bunch of traits which need to be in scope for this. (In a future episode, I'll circle back around and talk a bit about the way different items and scopes interact -- there's a lot to say there!) Rayon uses a pattern you'll see in a number of libraries: a *prelude*. Importing this prelude automatically brings all the traits you'll need into scope. This is one of the only times you *should* use a "glob import", i.e. pulling in everything in a given namespace without qualification. You usually want to pull in a specific name, or in my style more often a given *module*, to avoid clobbering other names in your own local scope. (You can imagine having your own `read` function, for example, and not wanting Rust's `std::io::Read::read` to conflict with it.) But in the case of a prelude -- or at least, a well-designed one -- the names which come in are just things which you'll have problems with if you reuse anyway. And that's the case here. So to most effectively use Rayon, you'll just include this declaration at the top of any module which uses it: ```rust use rayon::prelude::*; ``` Once you've done that, everything will *just work*. If you’re curious about what exactly the prelude pulls in, docs.rs has you covered, of course. The most important thing it’s imports is the `ParallelIterator` trait, which has to be `use`d (with the actual Rust `use` keyword) before you can, well, *use* it (in the ordinary sense of the word). We’ll talk more later about `use` and scoping, not least because there’s an RFC looking to improve the ergonomics of that right now! If you’re curious about that RFC you should check out episode 10 if the Request for Explanation podcast, where Aaron Turon is on the show to talk about it! For our purposes right now, we just need to know that importing the prelude with that glob `use` does the trick. ### The `join` API The other API Rayon provides uses a function called `join`, which actually underpins the parallel iterator API. `join` takes two closures and treats them as targets to run in parallel with each other. Notably, they're not *guaranteed* to run in parallel with each other, so it can actually be slightly slower to do things this way than doing them in sequence *if* all CPUs are already busy. The overhead is low. But it's there. This is a big reason to use the parallel iterators API: they use `join` under the covers, but they implement a sensible fall-back strategy for the times when you end up running in sequence instead of in parallel. That's something you have to manage by yourself if you're using the `join` API. Now, the flipside of that is: if you *need* every bit of control about how you will fall back to a sequential approach, `join` is what you want. Using join is pretty simple from the API point of view. You simply define the two closures to use and call `rayon::join(the_first_closure, the_second_closure)`. Then Rayon takes care of dispatching them – again, in parallel if possible, or in sequence if not. ### Bugs are still possible Now, Rust and Rayon save you from *data races* and *deadlocks*. You'll never end up in a spot where one thread wrote data right after the other but before a read happened leading to bad results; and you'll never have two threads ending up blocking each other because they're waiting on each other to release resources the other needs. The fact that we have explicit lifetime and ownership tracking as part of the type system makes it possible for Rayon to make that a firm guarantee. And hooray for that! However, there are some important caveats here. One is that if the closures you use with the Rayon APIs *themselves* use lock-based approaches to concurrency, rather than lifetime- and ownership-based approaches, you can still run into deadlocks. Another caveat is that data races and deadlocks are not the only kinds of bugs you face in dealing with parallel computing. They're an incredibly important class not to have to deal with, and in many ways getting rid of these make it easier to deal with the other ones. However, you can still shoot yourself in the foot if you use types with *internal mutability*. We talked about these a bit back in episode 16, but we didn't talk a lot about the mechanics of using them—that's *also* on my list of topics to get to in the future. For now, suffice it to say that types like `Cell` and `RefCell` can be *immutable containers* but have *mutable contents*—and yes, there *are* reasons you'd want this! But in the case that you're handing around an externally immutable but internally mutable object, you can *very* easily end up in a very, *very* bad situation. Shared mutability is the root of all evil. There are ways around this, of course: you can switch to "atomic" types, which only allow access in "atomic", i.e. one-at-a-time, fashion. or find another type which implements Rust's `Send` thread-safety trait. (That's another future topic!) But those have costs and tradeoffs as well. For one, atomic types perform worse than non-atomic types, because there is runtime bookkeeping associated with them. For another, it's still pretty easy to end up with *bugs* here, even if they aren't data-race bugs. Atomic data types are *not* like promise or future types; they don't have any sense of "eventuality" or locked-sequence to them. Trying to keep data synchronized across threads is no joke. And if you add in locking data structures to solve those problems, well… then you're back at the point of having locking data structures and you can have data locks. ## Outro Those caveats notwithstanding, Rayon is a really helpful tool for parallelization. For many cases, especially for those which are "embarrassingly parallel", you can essentially just swap Rayon's iterators in for the normal Rust iterators, and get parallelization essentially for free. If you haven't given it a spin, you should. Go find some places where your codebase might benefit from parallelism, and then use Rayon to parallelize your code *safely*—this is, after all, one of the great promises of Rust! ### Sponsorship Thanks to this month's $10-or-more sponsors: - Anthony Deschamps - Chris Palmer - Behnam Esfahbod - Dan Abrams - Daniel Collin - David W. Allen - Matt Rudder - Nathan Sculli - Nick Stevens - Peter Tillemans - Philipp Keller - Olaf Leidinger - Raph Levien - and Vesa Khailavirta As always, thanks as well to everyone who helps other people find the show---whether by just telling a friend, or by rating or reviewing it in iTunes or recommending it in another podcast directory, or by sharing it on social media! If you'd like to sponsor the show, you can do so by pledging monthly at Patreon.com/newrustacean, or by sending a one-off contribution my way at any of a number of services listed at newrustacean.com. You can find show notes for this episode, including links to docs and more for Rayon, at `newrustacean.com/show_notes/cysk/rayon/`. The show is on Twitter @newrustacean, and I am @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or – and this is my favorite – just send me an email at hello@newrustacean.com. Until next time, happy coding. ================================================ FILE: docs/cysk-rocket.md ================================================ # Crates You Should Know: Rocket ## Intro Hello, my name is Chris Krycho, and this is the New Rustacean podcast – a show about learning the Rust programming language. This is Crates You Should Know: Rocket. ## Overview As someone who works all day every day in the world of web development, I have to admit that as *fascinating* as many of the low-level projects in the Rust space are, and as incredibly *important* as many of the projects are for things like the reliability and safety of our software, this is one of the ones that makes me most *personally excited*. Rocket is a full-fledged web framework for Rust – probably the most fully-baked of the handful of actual web frameworks in Rust out there right now. One important thing to understand is that I’m distinguishing between a *web framework* like this and the underlying (and essential) tools like Hyper. Another important thing to understand is where Rocket is in the space – also by way of contrast, with Iron. (I may come back to Iron at some point, as well as some of the other fledgling frameworks.) Iron is a “middleware-oriented server framework” – which requires you to write yourself or reuse sets of middleware to build up your responses to each request. Rocket is much more in the general vein of a Django or a Rails, in the sense that it aims to give you many more of the pieces you need for many web applications right out of the box. There’s room and indeed *need* for both of those approaches to building web applications in this space, and I want to see both approaches thrive. At this particular moment in Rust’s history, though, I think the approachability factor for Rocket is really important. ### The Why Here’s why: being able to build your own middleware stack is incredibly powerful in one way. It lets you control every part of your stack, and carefully control every detail of your performance. However, it has the downside of, well, requiring you to manage every one of those details. To be sure, I think managing every last detail is probably more tempting for Rustaceans than for the average developer, but one of the things the Rust ecosystem needs is places where it is easy to get *started* – not everyone needs to be concerned with *every* detail everywhere. Put another way: sometimes you want to drill down that far, but other times, a nice abstraction goes a long way. And if it can be a really low or best of all zero cost abstraction, that’s a huge win. That is, in fact, one of the biggest bets Rust is making: that we can have *both* high-level abstractions and low-level performance. And Rocket is an attempt to provide a high-level abstraction for building the server side of a web application. ### The How When I say it does this while maintaining low-level guarantees, I mean it. But if you’ve spent time writing a high-level language and framework – like the aforementioned Django and Rails – you’re probably wondering how it can possibly be even in the same ballpark as those while also maintaining the speedy and low-level performance we’ve all come to expect from Rust. The answer, basically, is *magic*—where by "magic" I actually mean "procedural macros”. Procedural macros are a piece of the Rust story I haven’t covered yet, not least because they are (frankly) still not something I’m comfortable with. And in truth, most normal Rust developers don’t need to be deeply familiar with them, but they’re incredibly powerful and as such they’re profoundly useful tools for building type-safe but ergonomic abstractions like these. They’re also still unstable, which means that Rocket only works with nightly Rust for today. Procedural macros are a way of doing a full transformation of the syntax made available to you, at a much more sophisticated way than normal Rust macros support—but with the attendant complexity as well. You’re basically writing compiler plugins when you write a procedural macro, and that means that you’re responsible to make sure you are *correct* in the transformations you write. However, that power lets Rocket supply totally custom attributes, and those totally custom attributes are what make for its friendly and accessible API. I’ll come back to procedural macros in more detail in the future, both to talk about their future in light of RFC #1566 and to talk about how you can use them if you like... but all of that after I’ve written at least one myself! ### The API Rocket's API is primarily built around a combination of traits to implement, a set of custom annotation-type procedural macros, and a number of convenience macros of the macro-by-example variety. #### Important traits There are a number of high-level traits which your types can implement, and some of which they *have* to implement before they can be used with Rocket. - `Responder` is the basic trait which all types which you use as a *response* to a request must implement. - `FromData` lets you define how to transform some incoming data into your application's types. - `FromParam` lets you turn dynamic path segments in your route matchers into well-typed arguments to your route-handling functions. - `FromSegments` does the same basic thing but with *multiple* path segments, not just one. - `FromForm` takes HTTP form data and turns it into a type. - `FromFormValue` does the same thing with individual fields of a form. - `FromRequest` lets you transform incoming request *metadata*. This lets you do things like require API keys in a header, to borrow just one example. - `IntoOutcome` lets you define how to convert some type into Rocket's `Outcome` enum type, which is its way of representing the *three* states any given request can have: success, failure, or forward-to-the-next-possible-handler. (The `Outcome` type is kind of like a `Result`, but for HTTP request handlers, where a given handler may be able to *know* that something is a success or failure, but it also may *not* know that and should just pass it on). Not a trait but incredibly important is the `Request` struct, which defines an inbound request – but which you're not meant to use directly for the most part. Instead, you should usually use one or more of those traits methods to convert *from* `Request`s into your own local types. There are lots of other concrete struct and enum types you'll care about in building a Rocket application, of course, but those traits form the underpinning for the entire system, when combined with the procedural macros – that is, the custom annotations which allow you to have all the nice type-safe code which gets code-transformed into all the extra handling pieces you need. #### Attributes The most important of those procedural macros are the custom routing attributes. These are HTTP verb macros: attributes for defining that a function handles a request of a given HTTP request type at a given path, including any associated data from (for example) query parameters or the request body. The idea of using these kinds of attributes to define how a given function, well, *functions* isn’t an invention of Rocket, of course: with plenty of variation in the implementation details, it’s the basic pattern for everything from Python’s Flask framework to C♯’s ASP.NET MVC handle routing definitions. Rocket is smart to adopt that same basic approach – but it doesn’t just adopt it unchanged. Because procedural macros operate at compile time, it can do things and provide guarantees unavailable with decorators in Python or attributes in C♯, both of which are ultimately *runtime* items (though the pieces you use to *define* C♯ attributes are compiled much as Rocket's own code generation is). That means that Rocket can catch all sort of errors which would show up in runtime in other languages at compile time – a non-trivial win, if you ask me. This is one of the huge advantages of having a formal metaprogramming capability built into the language, and this kind of capability is a big part of why stabilizing the procedural macro system is a major and ongoing goal. The custom attributes Rocket defines are: - `route` - `get` - `put` - `post` - `delete` - `head` - `patch` - `options` - `error` Most of those are very nearly self-explanatory if you've done any web programming before: `get`, `put`, `post`, `delete`, `head`, `patch`, and `options` all just map directly to the standard HTTP methods, and define a route corresponding to that verb. The `route` attribute is something like a long-hand attribute for each of those: you can define a `route` which takes a specific HTTP verb method as its first argument and get the same result as using the verb shorthand. Each of them takes arguments appropriate to its type, including the ability to handle request body data, query parameters, and so on. Any arguments specified in the attribute are then type-checked – routes won’t match if the types don’t align. You can overload paths by providing a further argument, `rank`, which specifies the order in which to attempt the match. The last of these attributes, `error`, is a special case: it defines a class of handlers Rocket calls “error catchers.” These are just like the route handlers, but they only deal with error conditions – on a per error code basis. #### All together Once you have defined your types, defined the appropriate trait method implementations for them, and defined the routes, you just set up Rocket itself in your main function: you call `rocket::ignite().mount().catch().launch()`, where the `.mount` method takes a path to mount and a list of functions in a `routes!()` macro, and `catch()` does likewise with a list of error handlers supplied to an `errors!()` macro. It’s a very nice to use API: Rustic, just a little bit clever, and very efficient. I hope to be able to *use* it on a production app at some point, because I like it so much. ### Conclusion Hopefully that gives you some idea of how you’d tackle writing a simple application in a Rocket! I encourage you to take a look at the website for many, many more details on how all of this works—as well as to see a *marvelous* example of technical documentation. In addition to the Crate docs, there is also a great overview section and a really helpful guide section on the website proper. There are many technical details that make Rocket more immediately approachable than Iron – and again, that's not a dig on Iron, just an evaluation of what they're trying to be! – but more important than any of those technical details is the fact that Rocket has one of the best websites I've seen for *any* framework like this. If you're building a framework or library that you want to be adopted, I strongly encourage you to find a way to build documentation around it that is this thorough and well-considered – and to make it *look* good, even if that's just by making heavy use of Bootstrap or something like it. It really does make your tool more attractive. In this case, that's icing on the cake of a really interesting framework in its own right. You should *definitely* check out Rocket if you're looking to build something in the web world in Rust! ## Outro and sponsors Thanks to: - Anthony Deschamps - Behnam Esfahbod - Christopher Giffard - Chris Palmer - Dan Abrams - Daniel Collin - Matt Rudder - Ben Whitley - Peter Tillemans - Philipp Keller - Raph Levien - and Vesa Khailavirta for sponsoring the show this month. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website, or if you're a company interested in advertising to developers, get in touch! The other *huge* way people support this show is by helping others find it – by linking it on social media, sharing it directly with a friend, or even just rating or recommending it in a podcast directory. Thank you to everyone who has done that over the past couple years! ### Info Show notes for this episode are available not only in the podcast player of your choice but also at NewRustacean.com. You can follow me on Twitter @chriskrycho, or follow the show for retweets of Rust news @newrustacean – and if you have Rust news, feel free to tweet it at me and I’ll happily retweet it! That’s also one great place for giving feedback – others include the threads on Reddit, Hacker News, and the Rust user forums, as well as good old-fashioned email at hello@newrustacean.com. I’d love to hear from you! Until next time, happy coding. ================================================ FILE: docs/e000-script.md ================================================ "Hello! I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language." - Usual show format, this episode format (3 minutes) + Usual: any important news or follow-up (<5 minutes), then one or two topics of interest from what I've been learning, always with code samples available on the site and GitHub. It will be roughly weekly, but life does happen occasionally! I'm going to assume a basic working knowledge of programming, and along with it a basic knowledge of the command line, etc. I'm treating this as a podcast about being new to *Rust*, not new to *programming*. If you're interested in a show more about being new to programming in general, they're out there---and specifically, you can listen to Sap.py, the podcast I do with my wife as she's learning Python! On this, show, however, the focus is on Rust. + Today: you'll hear a little bit about me, then a lot about Rust! - Me (3 minutes) + Software * modeling networks of neurons in the brain, avionics, hazards modeling, web development * Fortran, C, maintained some awful C++, Python * Web: PHP, Node.js, Angular, SQL, and of course lots of HTML, CSS, plain old JavaScript, SASS, etc. + Seminary "Master of Divinity, which is a *hilarious* title" - Rust + What is it? (6 minutes) * Systems programming language * Memory safe. Really. No segfaults in safe code. And the vast majority of Rust code is safe code (e.g. Cargo: all safe!). * High-level design (inferred types, functional programming, generics, traits, metaprogramming via hygienic macros)---it's a descendant of ML (like OCaml or F♯), and it shows. * > To put it simply: it’s low-level in its ability to address the > computer, and high-level in the abstractions it hands to a > programmer. + What *isn't* it? (3 minutes) * A particularly beginner-friendly language. You *could* learn it as your first language, but I wouldn't necessarily recommend it. The language itself is relatively demanding, and the documentation is, too. It's possible, but I'd start with Python, Ruby, or JavaScript instead. * As of *today*, it isn't a classical "object oriented" language in the way that people tend to think of those things (i.e. in Java, C++, or C♯). It can *do* most of the same things, but it tackles the problems that inheritance is meant to solve in different ways. That said, inheritance is in the pipes: having more tools is good! + Why do I care? (3 minutes) * Time hunting bugs caused by memory leaks. Lots of it. * Writing in Python, etc.: integrating with Rust for performant code instead of C sounds *awesome*. * Performant, cross-platform back end for software I want to write * I just *like* it. + Why should *you* care? Well, all of the above reasons. If that hasn't persuaded you... just try it and see what you think! I find it a really *fun* language. + Get started: * rust-lang.org * users.rust-lang.org * #rust on irc.mozilla.org * Contribute! github.com/rust-lang - Subscribe/support + @newrustacean on Twitter and App.net + patreon.com/newrustacean ================================================ FILE: docs/e001-script.md ================================================ # e01: Document All The Things ## Intro Hello, I'm Chris Krycho and this is the New Rustacean podcast, a 15--20 minute show about learning the Rust Programming Language. This is episode 1. ## Fun News MSVC integration (the first pieces of which landed in 1.3) are coming along in the 1.4 beta (should land at the end of October). Huge for being able to use it with existing C codebases on Windows (like, for example, in one of my ongoing contracts). ## Docs ### Why do we care? - Just plain handy. No need to use external tools (Sphinx, Doxygen, JSDoc, etc.) because it has language-level support. + Predecessors: Python, Java + Modern, similar tooling: Elixir, Julia - Shapes the community: doesn't guarantee anything, but it makes good docs *likelier*. - Standardizes the docs. Python docs are all over the map---wildly different layouts, themes, etc. Finding things is hard ### `rustdoc` - Documentation comment types - Module-level docs + different kinds of documentation comments - Item-level docs + functions + structs and enums + members - How to use the command, and what you'll get when you do. + everything needed for that particular module in the format you see in package documentation online + Only publishes public items * More on public/private next week ### `cargo doc` - auto-builds full project docs and drops them in `target/doc`, just like `rustdoc` - the difference: automatically includes all public elements in a given project, so you don't have to run `rustdoc` manually over and over again! - limitations for full sites + `rustbook` tool + Rust and Cargo sites built using other tools to pull the pieces together ### What's next? ================================================ FILE: docs/e002-script.md ================================================ e002: Something borrowed, something... moved? ============================================= Intro (30s) ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is episode 2: "Something borrowed, something... moved?" News (4m) ---- - `rustfmt` -- a tool for formatting Rust code + [repo](https://github.com/nrc/rustfmt) + ["rustfmt-ing Rust`](http://www.ncameron.org/blog/rustfmt-ing-rust/) + [Reddit discussion](https://www.reddit.com/r/rust/comments/3nt2vm/rustfmting_rust_please_help_me_rustfmt_the_rust/) - Open RFC for incremental compilation -- valuable to decrease iteration time, especially on large projects (and available to other comparable languages). Right now, Rust compiles the entirety of a given "crate" (package) + [RFC issue](https://github.com/rust-lang/rfcs/pull/1298) + [RFC text](https://github.com/nikomatsakis/rfcs/blob/incremental-compilation/text/0000-incremental-compilation.md) ### About RFCs Rust, like several other communities (EmberJS), discusses suggested changes to the language and tooling via "RFCs", i.e. "requests for comment". People submit a PR with a detailed proposal, the tradeoffs, etc. and then the community discusses it. Once accepted, implementation. `struct` types (5m) -------------- ### Concepts - Data structures are fundamental - The kinds of structures you and have and what they can do empower/limit you. + True of language constructs in general: can you have standalone functions, or do they have to belong to a class (_a la_ Java, C♯, etc.) + Can you associate behavior with them (classes in classical languages, objects in e.g. JS)? + How do they relate to each other? * Classical inheritance * Prototypal inheritance * Mixins/traits - Two basic type constructors in Rust: `struct` and `enum`; today, focus on `structs` (the simpler of the two). Also tuples. - No inheritance (yet) ### Use - `struct`s have *members* - Members can be any type: primitives, other `struct`s, functions - Roughly like C++ or Java classes in many ways, but without inheritance, and + Rust has no header/source distinction as in C++ * use documentation tools, etc. instead of reaidng header files. Cf. Python's `help` etc. + but implementation still separate from definition (in `impl` blocks) - Double colon notation for methods - Dot notation for member access Borrowing and Moving (7m) -------------------- ### Concepts - A core problem in languages with memory management is knowing the state of a given piece of data - "Shared mutable state is the root of all evil" - Rust addresses via "ownership" + unlimited immutable references + max one mutable reference - When handing data to one function from another, the data can be *borrowed* or *moved*. - If you *borrow* data, you get a "reference". + Not the same as other languages---though some similarities under the covers + Means you don't *own* it, you just have access to it at some level. When done, control goes back to caller (owner) - If you *move* data, you get *ownership*. + You can do anything allowed by mutability rules of the type in the new owner. + On exiting the new owner's scope, the object is *dropped*---memory is de-allocated. + As a result, original owner can't access it anymore. ### Use - References use `&`. - The `*` operator dereferences, allowing you to assign new values to the referenced element (e.g. a new `struct` instance entirely, not just operating on the internals of a given `struct`). + But as always, only for mutable references. + It does a bit more than that, too; we'll come back to that in the future when we talk about traits. - Moves happen in function calls when using non-reference types - Can use `move` keyword to specify moves in other contexts as well -- more on that in a future episode (when I understand it better myself!) It's both *like* and *unlike* C/C++/etc. Closing (1m) ------- ### Next time - Another data structure type: `Enum`s! - The associated notion of pattern matching---one of the most powerful concepts in Rust. - Meaningful, safe return values from functions which might fail ### Follow/support - Follow: Tw, ADN (NR, then ck) - Support at Patreon - Show notes at NewRustacean.com, with links to content, Rust reference, social media, etc. Until next time, happy coding! ================================================ FILE: docs/e003-script.md ================================================ No More Nulls ============= Intro (30s) ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is episode 3: No More Nulls. News (2m) ---- - Shout out to GitHub user romankl, who submitted a PR to the show to fix an error in a link. So good! - Work on IDE support! + My chosen tool: JetBrains/IntelliJ + Also: Eclipse, Visual Studio - Learning tools I just heard about: + Rustlings (Carol Nichols) + Rust FFI Omnibus (Jake Goulding) Overview (3m) -------- Why do we care? - Meaningful return types. + C special error values + C/C++ `void`, Java `null`, etc. - Pattern matching -> sophisticated way of handling things that goes way beyond what a `switch/case` statement can do, and `enum` types are a great way to start with those (though enums can do much more, and so can pattern matching). enum types (4m) ---------- - Sum types vs. record types (i.e. enums vs. structs) - Differences between these and C/C++ types - Things enums can hold Pattern-matching (5m) ---------------- When matching against a pattern---any pattern, not just enums!---the pattern match must exhaustive. If you forget something, the code won't compile. - Not like if/else blocks where you can forget conditions - Kind of like switch/case blocks, but not limited in the same ways (can match on any type, and on different types described by enums) Lots of places where this might be useful: - handling return values exhaustively (more in a minute on this) - writing a finite state machine - interpreting responses from an API - parsing tokens in an actual parser What kinds of things can you match? - Ranges of numbers - Enums - Strings - Tuples - etc. You can also deconstruct these complex types to act on them. Match arms are expressions, so you assign the result of a `match` to a variable (more on this when we talk about expressions in a future episode). Meaningful returns (2m) ------------------ One place pattern matching and enums combine to become extremely powerful is in handling return statements. - `Option` - `Result` Closing (1m) ------- ### Next time - Functions in Rust! + Regular functions + Methods + Closures - Gives us a good excuse to talk a bit about the "stack" and the "heap" as well; we'll *introduce* those ideas along the way. ### Follow/support You can find show notes with detailed code samples illustrating these ideas, as well as links to things mentioned on the show, at NewRustacean.com. You can also follow the show on Twitter or App.net @newrustacean, or follow me there @chriskrycho. If you like the show, please rate and review it on iTunes to help others find it, and if you *really* like the show, I'd welcome your financial support at Patreon.com/newrustacean. Last but not least, I'd love to hear from you on social media, in the thread for the show on users.rust-lang.org, or via email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e004-script.md ================================================ Functionalized ============== Intro (30s) ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is episode 4: Functionalized. News (2m) ---- First up, thanks for sending in more pull requests! - Thanks to kstep (Konstantin Stepanov), Dashed (Alberto Leal) and ctjhoa (Camille TCHOA) for fixing some links in the show notes. - Thanks to zazdxscf (Emanuel Czirai) for pointing out some problems in the code samples from last week! - Thanks to David Krycho (yep, that's my dad!) for asking me some good questions about last week's episode content and show notes, which have led to some improvements I'll push up to the example code sometime later this week! Second, progress continues apace on the IDEs I mentioned last week: the IntelliJ IDEA folks have made a *ton* of progress since I recorded, and though you have to build the plugin yourself, it does support some of the basic syntax highlighting functionality and the like. Third, a few more learning tools you might find handy: - Exercism.io has some Rust exercises (HT: Lechindianer on GitHub/Tw/ADN) - Camille TCHOA's GitHub repository rust-learning - If you speak German, rustplatz.de. I can't read a word of it, but it looks like there's some solid stuff on there (again via Lechindianer) Overview (3m) -------- Last week, I said we were going to talk about functions, methods, and closures, and that's sort of true. However, to talk about functions in Rust, we're going to have to spend a little time talking about *types* as well, and that means we're not going to get quite as far in our discussion of functions as I originally thought. Today, after getting our feet under us a bit with what we actually mean when talking about "functions" both in general and also in Rust specifically, we'll cover the very basics of how Rust handles normal functions, methods, and closures. We'll conclude by showing how some of those conceptual issues come into play by showing how you can pass around functions as arguments, precisely because functions are just another type in Rust. Next week, we'll pick up and carry on with the idea of *returning* functions, and see how that leads us further into the type system and into how Rust manages memory. Functions (High Level) (5m) ---------------------- Functions: building blocks of sane programming practice. Who *hasn't* seen nightmare code where functions were thousands of lines long and did dozens of different things? How functions work, and what they are in the language, make a huge difference in how your language feels and what kinds of things are normal in it. - Are functions first-class members of the language, at the same level as any other object (whether an integer or a struct/class/etc. instance)? - How hard/easy is it to use functions in composition? - Are there anonymous functions? - Are there closures? - Are there methods? - Are there non-method functions? - Can you define functions inside other functions? - Do functions have types, and can you use those types the way you can use other types in the language? How your language answers these questions determines what kind of language you have. For example: - Old-fashioned Fortran has *subroutines* more than it does *functions*. They are capable... as subroutines. But they're not high-level functions, at all. - C and Java, for all their differences, answer many of these questions the same way. The main way they differ are in having methods. Neither can *really* treat functions the same way they treat, say, integers. - Python and Ruby, by contrast, have functions that can be assigned and managed just like any other type in the language. In Python, functions are objects, which can have methods attached! However, Python doesn't really expose the *type* of the function in a way that you can use (as indeed it doesn't with *any* types, relying philosophically on duck typing instead). - In Haskell and ML-descended languages (OCaml, F#, and Rust!), functions have types, and can be used as such. Functions in Rust (3m) ----------------- - A theme of Rust is *strong, static typing*. Nearly everything in the language has a type, which is known at compile time---functions included! - Basic components of the type of a given function are its argument types and return types. - Talk more about types in the future, because those types can be further constrained in various ways. - Methods are a special case of ordinary functions: and (from what I understand so far) they only get special behavior when passed a reference to Closures (2m) -------- Big difference with closures from functions (anonymous functions) is that they capture their environment. Use slightly different syntax to emphasize this. - Gets into ownership and another Rust concept, *lifetimes*, because they maintain access to elements defined in their scope. - One way of doing information hiding (and easily the most common in e.g. JS). Closures and functions both implement the `Fn` `trait`. (This is one of the ways that types can be constrained and defined!) We'll talk more about traits now; today suffice it to say that traits make up the basic way of defining conformity to a given interface---_a la_ mixins, protocols, and interfaces in other languages. Functions as arguments (3m) ---------------------- - Both normal functions and closures can be passed as arguments. - Closures particularly useful for two reasons: + They can be defined where the function call happens, so for brief definitions this can be clearer (e.g. `map` or `reduce` on an array). + As noted a minute ago, they can bring their environment with them. Scenario: say you have a function that expects a function taking one argument as a callback, but you need to do some manipulation in the function you pass in using data in your *current* environment. Two alternatives: 1. Use a closure directly, where you just have access to the local data you need without passing it as arguments. 2. Create a factory to build the function you need... by creating and returning a closure. This is a bit more complicated, but there are times when it's the best way to approach the situation---especially when the body is complicated, or when you need to build similar functions repeatedly. - To define a function taking a function as an argument, you just supply the *type* of the function as a `trait`. Then the operation is *generic*: it can operate using any function that matches the constraints defined by that trait. See the code samples to get an idea of how this works in more detail. Closing (1m) ------- ### Next time Last week, I said we'd get all the way through functions and into the stack and the heap, but as it turns out, there is a *lot* to cover in functions. So, next time we'll pick up from here and talk about returning functions, and *that* will lead us into a discussion of the stack and the heap, and possibly---but no guarantees!---into some early discussion of functional programming. ### Follow/support You can find show notes with detailed code samples illustrating these ideas, as well as links to things mentioned on the show, at NewRustacean.com. You can also follow the show on Twitter or App.net @newrustacean, or follow me there @chriskrycho. If you like the show, please rate and review it on iTunes to help others find it, and if you *really* like the show, I'd welcome your financial support. You can set up recurring donations at Patreon.com/newrustacean, or one-off donations at dwolla.com/hub/chriskrycho. Last but not least, I'd love to hear from you on social media, in the thread for the show on the Rust user forum at users.rust-lang.org, or via email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e005-script.md ================================================ Allocate It Where? ================== Intro (30s) ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is episode 5: Allocate It Where? News (2m) ---- Rust 1.4 release! Highlights: - New chapter in book on error handling (great complement to e003) - Full MSVC support for 64-bit builds - One language change, the details of which are (frankly) still a bit beyond me! I'll link it in the show notes. As usual, it's a "functionally semantically versioned" change: it *technicalLy* breaks backwards compatibility, but because the Rust core team can run the compiler on every single package on crates.io, the actual impact to the community isn't that. Given the limitations of a programming language, as opposed to a library or framework, that's excellent. - I contributed a little bit! Not much, and nothing important---just cleaning up a few things in the build tooling around documentation---but it's still fun to be able to say. As I've said before: jump in and contribute! Overview and review (1m 30s) ------------------- Last time, we were talking about functions in Rust, and in particular about using functions as arguments to other functions. I had originally intended to discuss *returning* functions as well, but needed to take some time to discuss both type systems in general and Rust's type system in particular as preparation for the discussion of Rust's functions. Today, we'll pick back up and jump in with a discussion about returning functions, and that in turn will lead us into an initial discussion of the stack, the heap, and why we need to care about the difference between the two when dealing with functions. Note that I'm going to assume everything from last week's episode as a baseline here. Now, let's dive in and see how to return functions from other functions! Returning functions (a) (2m) ----------------------- - Both normal functions and closures can be returned from a given function, and the definition of each is essentially the same, with the usual variations in syntax between the two of course. - If you've done this in other languages, including Swift, you'd expect that the return type would just be a function specification, just as when defining a function type as an argument. And you'd be almost right, but if you try that in Rust, you'll get a compiler error: it'll tell you that the types are mismatched, and part of the error will point to the lifetime of the object created: it'll say you need a `'static` lifetime (we'll come back to lifetimes fairly soon... right after I get a better handle on them). - If you start chasing the normal course of how to fix that, you'll quickly end up in a messy spot... and still won't be able to fix it. For particular details on that, see both Rust by Example and the Rust book. - As it turns out, the solution here is to use the `Box` type and construct a "boxed" version of the function. - So, what is `Box`? It's a way of allocating an item on the heap, rather than on the stack. The stack and the heap (6m) ---------------------- Okay, but some of you might be coming in from languages like Ruby and Python, where you rarely (if ever) think about the stack and the heap. - For starters, I'll link a really fantastic explanation on Stack Overflow in the show notes, and really if you're going to do any kind of low-level or systems programming, you're going to need to get familiar with this. - Here's a *really* brief overview, summarized to the best of my ability. I will freely admit that this is an area where *I* need to be stronger, so do let me know if I get a detail wrong along the way; I'll happily add any such corrigenda to the show notes. - Both the stack and the heap are allocated by the operating system, but they are very different in nature, purpose, and behavior. - The stack is a last-in-first-out data structure, and if you've ever seen a "stack trace" in your debugging, you've seen a bit of how it works: each function call essentially layers on top of the previous one. All memory needed for the data for a given function---all its local variables---gets allocated on the stack for that particular function. - This works because the stack size for a given function can be known at compile time, and therefore can be fixed for run-time calls; this is what makes it possible to use it as a stack for function calls. It is also the most significant limitation of the stack: what about a data structure whose size you *don't* know ahead of time? Or what if a given data structure needs to change in size over time? You can allocate the pointer to the data structure when you create the stack, but you can't allocate the *whole* stack size in those cases. This is why C doesn't let you create dynamically sized arrays, for example: arrays are stack-allocated. - What we need is a way to allocate space dynamically. That way is the heap. - As you can imagine, the heap is a substantially more complicated data structure. Not only does it entail not knowing ahead of time what size the allocations will have to be, it also involves data that isn't local to a given function, so you suddenly start having to deal with access control and allocation and deallocation timing issues. - One common example of a type in Rust which is always heap-allocated is its `Vector` type, which is a dynamically growable array-like type---and because it's dynamically growable, it *must* be heap-allocated. - What about other types? Well, normally all values in Rust are allocated on the stack, rather than on the heap (with the obvious exception of special, always-on-the-heap types like `Vector`s). That includes functions! - `Box::new` heap-allocates them instead. Unlike memory dynamically allocated with `malloc` in C, though, `Box`ed items get still cleaned up automatically in Rust when they go entirely out of scope; the compiler makes sure that any cleanup code necessary is executed (in the `drop` method on a given type) and then the reference becomes unavailable. Returning functions, (b) (6m) ------------------------ Now that we have some idea what's going on with the stack and the heap, we can come back to talking about returning functions from other functions. As I said at the beginning of the episode, the solution to this particular dilemma is to use `Box::new` when returning functions from functions. We can do this because functions are still just another type in Rust, we can handle this case just like any other case where we need to heap-allocate something! This is one of the *many* places where having functions that are first-class members of your language comes in handy. It's worth noting that functions get allocated in memory somehow or another in *all* languages; the question is how obvious this becomes to you as a programmer. In this case, we have to be pretty explicit about it. But it does raise some questions. After all, it's great that this solves our problem. But... *why* does this solve the problem, and for that matter, why do we have to solve this problem at all? - Functions are generic types. Right now, the Rust compiler only supports returning concrete types, and generics aren't concrete. - As an aside, this concrete type issue is actually true of generic types of arguments, too, but the Rust compiler gets around that by going through and creating actual concrete types for all forms of a given generic function which get called in a given program. - References *are* concrete, though, so we might be able to return a reference, right? Well, unfortunately, no: references need *lifetimes* so that the compiler knows how long to hold onto the memory being referenced. Again, lifetimes are a topic we will come back to in the future. For today, it is enough to know that for reference types, the Rust compiler needs to know how long to hold onto the reference, and lifetimes give us a way to do that explicitly when we need to. - Fight with this as we may---and there are a lot of ways you might try to work through this, as both the code samples in this episode's show notes and the Rust book's discussion of the topic demonstrate---you can't win. Returning a stack-allocated reference to a stack-allocated function is not something the compiler will let you do. - For the record, this is a good thing: it is part and parcel of the memory safety guarantees that Rust makes. It just makes certain cases a bit more work. Like this one. - In any case, there is a solution to our problem. As you've by now guessed, we don't have to stack-allocate the functions. We can use `Box::new` and heap-allocate them instead. Then we have a smart pointer reference to the function instead. Conveniently, this solves all of our problems at once. + They will be cleaned up automatically, so we don't need to worry about lifetimes anymore. + Boxed types are smart pointers---that is, a kind of reference---so we have a concrete type we can return. So there you have it: you *can* return functions---whether plain old functions, methods, or closures---from other functions. You just have to heap-allocate them explicitly. And now we know *why*! There's still one really important part of closures we haven't talked about, and that's using the `move` keyword, but we'll come back to that in the future when we talk more about ownership semantics! Closing (1m) ------- ### Next time Next time, we're going to take a bit of a step back up to a slightly easier, slightly higher-level concern and talk about modules and packages---a.k.a. ] crates---and API design. Because I've been playing with some APIs in Rust, and some of them I like, and some of them... not so much. How we structure our code matters, it turns out! ### Sponsors Thanks to Chris Patti for sponsoring the show this month! If you have any interest in Python, go take a listen to `Podcast.__init__`, a podcast he co-hosts; they're interviewing tons of interesting people in the Python community. ### Follow/support You can find show notes with detailed code samples illustrating these ideas, as well as links to things mentioned on the show, at NewRustacean.com. You can also follow the show on Twitter or App.net @newrustacean, or follow me there @chriskrycho. If you like the show, please rate and review it on iTunes to help others find it, and if you *really* like the show, I'd welcome your financial support. You can set up recurring donations at Patreon.com/newrustacean, or one-off donations at Venmo, Dwolla, or cash.me. Last but not least, I'd love to hear from you on social media, in the thread for the show on the Rust user forum at users.rust-lang.org, or via email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e006-script.md ================================================ Modularize this! ================ Intro (30s) ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is **Episode 6: Modularize this!** Resources (1m) --------- A couple things came across my radar this week that you might find interesting as you're learning Rust. - Roguelike in Rust---a tutorial walking through the process of building a text adventure using Rust. - A screencast by Intercom with Yehuda Katz (of Ruby, EmberJS, and Rust fame) on using Rust as a replacement for C for performance-critical modules with Ruby code (but readily applied to other languages like Python, etc.). Overview (1m) -------- We've spent the last few weeks talking a lot about functions, and for good reason: functions are the basic tool for building programs. Today, we're going to turn our attention to a related set of ideas in Rust: modules and "crates," Rust's name for what you might know in other languages as *namespaces* and *packages* respectively. Together, these two give us the tools we need to *organize* all those structures and enumerations and functions we discussed. Why do we care? Well, because it is difficult to understand, to organize, to reuse, or to maintain any large set of code without these tools! We'll take them in turn. APIs (5m) ---- An API---originally "application programming interface" but now used more generally to describe the interface between libraries as well---is defined by the publicly available set of functions and data types, and their organization. We have enough data now to start thinking about APIs and the way they are structured, because we now know about all the basic building blocks for defining them in Rust. We had to wait until today, though, because until you know how a given language allows you to *organize* your data, you can't really talk about an API. But now we need to talk about APIs, because the API for a given library or program matters, and it matters a *lot*. A little over a week ago, I took a look at some code a friend was working on as he played with a Rust library. He was having a hard time getting the code to read nicely, with multiple nested `match` statements. As we looked at it, we both found ways to work around that, including for my part writing a small macro for the first time, but our conclusion was that the API itself wasn't great. In this particular library, the problem was the way the `Option` and `Result` types were used: things were wrapped too many times in one or the other or both, so that nearly every operation in the library required pattern matching or unwrapping values. That highlights one of the major issues in API design: you don't want to nest things deeply---whether in modules or in complex data types---unless there is a *very* good reason to. To quote the Zen of Python: *flat is better than nested*, and *simple is better than complex*. With Rust's module and type systems, we have powerful tools we can use to model data in a powerful way. However, we still need to take care to design our APIs with those maxims in mind. The fact that we *can* nest things fourteen modules deep and wrap everything in `Result`s inside of `Option`s inside of `Result`s inside of `Option`s doesn't mean we *should* do that. You might be thinking, "Well, but in *my* library, that complexity is necessary!" Beyond the obvious question---is it *really*?---it is important to remember that one of the points of building a library is to *hide* the complexity of doing whatever your library does from an end user (first of all yourself in most case). In other words, our goal in most cases is to provide a useful abstraction which makes it so that end users *don't* have to deal with that complexity. One helpful approach is to take advantage of the difference between public and private modules and functions: if you need that complexity *within* your library---and sometimes you really do---then use it appropriately. But don't unnecessarily expose your API's consumers to that complexity: supply flatter, simpler data structures and functions to them however possible, with as flat a namespace as possible, to make it easier to use your library. So, how do we do that in Rust? Packages (5m) -------- Packages, the highest level of abstraction for organizing Rust code, are the organizational level which correspond to and indeed get built into libraries in Rust. Here, we call them "crates." (Thus the name of the Rust package manager, Cargo! Rust's naming choices are quirky... but I like them.) Language-level packages, especially when combined with a hosting solution and a tool for managing them, are extremely handy. Although they can have their downsides---dependency resolution can be painful---these tools are a major part of what has made ecosystems like those around Python, Ruby, and NodeJS so effective. Nor is this just a "scripting language" concern: even languages like Java and C# have had package managers for some time, now. Having used them extensively, I feel their absence keenly in C and C++, where no solution has really caught on with the community: largely, I suspect, because those communities grew up long before package managers became a norm. With Rust and Cargo, we are trying to learn from the best and worst parts of the existing ecosystems. Every generation of programming languages and tools has the chance to learn from preceding generations, and just as Ruby's packaging tools improved on Python's in a variety of ways, and Node's npm represents, if not a clean win, then still a useful experiment, Rust now has a chance to take those lessons and apply them again, but in the slightly different context of a statically compiled language. We define packages in Rust using a `Cargo.toml` file; TOML files are just a lightweight markup a lot like the old ini format. The format for these files is specified in some detail on crates.io. The main thing is that we define the path to the main source file for a package and give it a name there. (Helpfully, running `cargo new` on the command line will help us do this automatically.) For libraries we want to reuse, or distribute, that root file is usually at `src/lib.rs`, and for binaries, at `src/main.rs`. Analogous to a Bundler lock file, or the output from `pip freeze`, Cargo generates a `Cargo.lock` file when you generate a build. This specifies not just the basic dependencies you specified, but the *exact* versions used when you made the build. This makes it possible to have readily reproducible builds---which is a big deal, as anyone who's spent time with npm knows! Once we have a crate we're happy with, we can then upload it (and the docs we built for it!) to crates.io, and make it available for others to use in the same way if we so desire. Crates are also the basic unit we can use for linking Rust with *other* programming languages---see the screencast by Yehuda Katz that I mentioned at the beginning of the show for an example. Modules (5m) ------- One of the two major ways we break down the functionality of a given library is through what are often called *namespaces*. Names are one of the hard problems in software, and in particular we need to come up with a way to handle the situation where you and I both name a function the same thing. You can imagine, for example, a regular expression library, a compiler library, and an HTTP request library all implementing a `parse` function. Which one are we referring to? How should the compiler know whether the function call we are making is valid or invalid if it needs to choose between variants (especially if we don't have overloading---and we don't, in Rust)? The common pattern for this is *namespaces*. In C++, these are managed through namespaces. In Python, they come in *modules* and *packages*. In Rust, they come in *modules*. - Modules are the basic structural tool for organizing discrete groups of code in Rust. - They're very similar in many ways to modules in Python (though with some important we'll get to momentarily), and to namespaces in C++, even sharing some of the basic syntax of the latter. - You define a module in Rust by using the `mod` keyword. - Just as with other items which make up the contents of module, modules themselves can be declared public (with the `pub` keyword), but are private by default. That is, you can define a bunch of modules (whether in the same file or an external file) for organizational and namespacing purposes, but you don't have to expose all of those---whether to other external modules, or at the package/crate level. - As my comments so far have suggested, you can define multiple modules in a given file, using curly braces to a block which defines the contents of that particular module. - As you can imagine, though, this gets unwieldy quickly for a package of any substantial size. - Thus, the modules declared with the `mod` keyword can map to *files*. For example, the show notes for this episode are declared as `pub mod e006` in the `lib.rs` source file which defines the root of the package. The file itself is just named `e006.rs` and lives at the same level as `lib.rs` in the project structure. - You can also use folders to organize your modules (somewhat like you can in Python, but with the difference that files and folders do not *define* the module structure the way they do by default in Python). - If, for example, I wanted the show notes for each episode to live in a folder instead of just a single file, the notes for this episode would be at `e006/mod.rs`. - To use another module, you use the `use` keyword and specify the name of the module. If it is a nested module, you separate each name with a pair of colons. The full path to this episode would be `show_notes::e006`. - You can also reference specific items in a given module by referencing them in the same way. If you want to reference more than one item within a module, you can supply the path up to that module as usual, and then wrap all the items you want to `use` with curly braces, separated by commas. - The `use` statement lets you alias modules or items, too. If you have some long module name that you're going to reuse frequently, you might give it a short name. (Pythonistas might think of the common pattern of importing numpy as `np`, for example.) - One last thing we can do with modules: we can re-export a given module. This is convenient for defining the top-level interface to a given package. If you have a reason to have a deeply nested file structure, you might still be able to supply a nicer API to the package by re-exporting those modules at the top level, or at least a higher level, so there is a friendlier interface for people using the crate. Closing (1m) ------- ### Next time And that's a good spot to wrap up for this week! Next time, we'll talk about *testing in Rust*. ### Sponsors Thanks to Chris Patti for sponsoring the show this month! See the list of other sponsors in the show notes. If you'd like to sponsor the show yourself, you can set up recurring donations at Patreon.com/newrustacean, or one-off donations at Venmo, Dwolla, or cash.me. ### Follow/support You can find show notes with detailed code samples illustrating these ideas, as well as links to things mentioned on the show, at NewRustacean.com. You can also follow the show on Twitter or App.net @newrustacean, or follow me there @chriskrycho. If you like the show, please rate and review it on iTunes to help others find it. Last but not least, I'd love to hear from you on social media, in the thread for the show on the Rust user forum at users.rust-lang.org, or via email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e007-script.md ================================================ Testify ======= Intro (15s) ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 7: Testify*. News (2m) ---- The big news as I release this is that Rust 1.5 came out last week. From the perspective of other languages, that seems a little crazy: since I started this podcast, we've had two point releases, 1.4 and 1.5, and 1.3 came out shortly before I recorded the introductory episode. Rust is keeping up with its promise of "stability without stagnation", and frankly it's really fun to watch. One of the great things about the release trains model pioneered by Chrome and since adopted by many other projects, including Rust, is that you get forward motion frequently, though the size of the changes in any given release may be relatively small. Rust 1.5 isn't a big release in terms of features. For the most part, it was just fixing a bunch of little things in the language design and updating tooling around the language: **cargo** got a new *install* command, and a bunch of the standard library functionality for dealing with the file system and file paths was stabilized and so is now available on the main release. In practice, this means that if your code worked last week, it will continue to work this week; it will just compile faster and you'll have some new tools to use. Only one other thing particularly caught my attention in the last couple weeks, as I've been busy with travel, but that thing was extremely interesting. Sean Griffin, a guy who is currently employed to work on Rails and particularly its SQL tooling has released Diesel: a Rust SQL ORM and query builder. My initial impressions are that it is really interesting. It is an attempt to build an easy-to-use Rust toolkit for dealing with SQL, while also providing the great type safety guarantees that make Rust so attractive You can listen to Sean talk about it a bit on episodes 31 and 32 of The Bike Shed. Overview (4m) -------- Onward! Time to talk about tests! Why? Because tests help us know whether our code is broken. A good test suite gives you two good things: 1. It tells you whether your code does what you think it should presently. 2. It lets you make changes and tell whether your code *still* does what you think it should. Importantly, to the extent that you've written a good set of tests, it can do those things far more rigorously than you can by repeating a set of tests manually. The computer won't forget a test in your test suite. If you catch a new bug, you can just add a test to the suite, and when you fix it, you can be sure that it'll be caught by the computer if you do something that breaks it in the future. That's incredibly valuable. Again, the qualifier, though: your tests can't guarantee the correctness of your program. They can, however, help you be *more* sure that it is correct, if there are enough tests, of the right sort, and they can help you be sure that even if things are broken, they stay broken in the same way between changes. That's still quite valuable in its own right, though! There are two big categories of tests: unit tests, and integration tests. Rust has support for both. But first, a note on how unit tests especially might look a little different in Rust than in other languages. In dynamically-typed languages like Python, Ruby, or JavaScript, one of the major functions of unit tests is to verify that functions treat their arguments correctly, including if you hand them invalid types, and that they return not only the right values, but even the right *kinds* of values. You don't want a function which is supposed to convert from a string to a number to hand back a string, for example. Many of *those* kinds of things are taken care of by the compiler itself in Rust and other statically typed languages. (This is one reason that test-driven development is much more popular in the communities around those dynamically-typed languages. Another is simple history: unit testing as a practice simply developed after C was well-entrenched, and the tooling around it has never been as good as a result. Many modern languages, including Rust and Elixir, have built-in support for testing, and this makes it far more likelier that developers *will* write tests than if they have to use a third-party framework.) Even though static compilation with a strong type system solves one set of problems, though, it doesn't tell you whether the *values* you got out of a function were correct. Knowing that you did in fact get a number out of a function which converts strings to numbers helps---but did you get the *right* number back? Testing that requires that we actually call the function with an input whose result we know ahead of time and see what we get. Unit tests, in other words! In Rust, you probably won't find yourself writing as *many* tests as you would in Ruby or Python or JavaScript, but you still need them. The compiler doesn't guarantee anything about your algorithm; all it does is tell you whether you handled your types correctly. Tests in Rust (11m) ------------- ### Overview (0.5m) There are three basic kinds of tests in Rust: test functions, documentation tests, and integration tests. In addition, nightly Rust supports benchmarking, which a different sort of test but an important one. ### Attributes (2m) In order to talk about testing, however, we first need to talk about a set of flags we will be using around the modules and functions we will use for testing: *attributes*. - Attributes are special flags set to tell the compiler to do something with a given definition---whether of a module, a `struct` or `enum`, or a function. - They are currently defined by the compiler, and *only* the compiler, in stable Rust. You can define them yourself using compiler plugins, but compiler plugins are an unstable feature: the Rust core team has not decided on the best way to handle them going forward. What are attributes used for? Lots of things! - As we will discuss in a minute, they can be used to specify tests. - `#[derive]` can be used with relatively straightforward data types to create default debug and display formats, so that you don't have to define the formatting for most structs, for example. - `#[cfg()]` can be used to specify configuration for modules used by **cargo** as well as by **rustc** and **rustdoc**. - `#[feature()]` is used to turn off or on specific features, useful when dealing with nightly Rust builds, where some features may be available in master but disabled by default because they aren't ready for release. - As both of these last two imply, some attributes can take *arguments* which further specify their behavior. You get the idea; there is a lot more we can say about attributes in the future, and we will, but that's enough to get started for talking about tests. ### Test functions (3m) - Functions marked with `#[test]` are treated in a unique way: when running **cargo test** on the command line, **cargo** executes each function marked with the attribute, and indicates whether the test returned successfully. - These functions are never compiled into your release code. This is great: it means you can write your tests right next to the code they check, without impacting the size of the executable you distribute. - Within tests, you can also use a set of dedicated macros like `assert` and `assert_eq` to indicate how you expect something to behave. - If the result of some function call *should* be broken, that is, it should "panic", you can set the `#[should_panic]` attribute on the test! Also, you can supply an argument to `#[should_panic]` to account for specific *kinds* of failures in a test. - You can also set an `#[ignore]` to tell **cargo** to ignore certain tests by default. You can then override that by passing an extra argument to **cargo**---handy if you have certain tests which take a long time to run, for example, and only want to run them occasionally. - The best practice is to wrap tests in a module private to the containing module, and set the `#[cfg(test)]` on the module. This lets you write support functions within that module which are excluded from normal builds just like functions marked with `#[test]`. - (By convention, we call that module `test`, but it *must* be marked with the `#[cfg(test)]`.) So that's how you *write* these kinds of tests. What would you use them for? Well, this is where you would put unit tests. Within the `test` module, you can verify that the various functions you call work as expected, by comparing the results of a function with their expected results. This is particularly powerful when combined with Rust's expressive type system, because you can, for example, test functions to be sure that you actually get both the right enumeration and the right value within it from a function which returns an enumerated type. For the simplest example, you can just check that calling a function which returns an `Option` gives you either a `None` or a `Some` with a value in it, and also check that the value is what you expect. ### Documentation tests (2m) The second type of test we have available is a "documentation test." Like Python and Elixir, Rust can run any samples you include in your documentation strings, and in fact **cargo test** will do exactly this. And this gets you something distinct from what unit tests give you: it helps you make sure that your documentation itself is correct and up to date. If you change an API, but forget to update the comments on the module to reflect that, **cargo test** will give you a failure, and point you to the docstring! (Note that this only works for library crates, not binary crates. In fact, this is true of tests in general. I haven't yet had a chance to look for the reason that is so; I'd love to hear about it.) Any and all code samples included in your documentation blocks will be executed. Conventionally, we mark off a section with a first-level header titled "Examples" for these kinds of things, but **cargo test** will catch *any* code in your samples. If you want to turn off a given example (e.g. because it is supposed to fail), you can just add `ignore` to the very start of the code block, and **cargo test** will ignore it. On that note: thanks to GitHub user **raindev** for submitting a pull request for the show notes which did just that for some of the negative examples in the notes for episode 5! ### Integration tests (2.5m) That covers most of the kinds of things we might want to do with the code in a given module. What about testing that all the pieces we've written work together, though? For this, we have integration tests. The best way to do this is to come at it just like we were any other external user of out library: import the pieces we want to test and check that they work as expected. So we can create another library-type crate, add functions marked with `#[test]`, and run **cargo test** on that crate. The standard practice for Rust projects is to name that test crate `tests`, just to be clear what the crate is for. These kinds of integration tests can help us be sure that our public API is behaving as we expect, that its pieces work together as they should, and indeed that our public API is actually what we think it is. If, for example, we forgot to make a given module or function public with the `pub` keyword, an integration test that tried to `use` it would fail. Now, what kind of thing would you use this for in particular? Imagine you were writing yet another Markdown parser: you might want to have parse and render functions. Within the unit tests, you would have tests that handle specific kinds of elements, which you would compose together to create the actual parsing functionality. To test whether a given document resulted in the result you expected, though, you would probably need a non-trivial Markdown document to run through your main public parsing and rendering function or functions. As with the unit tests, this would give you a straightforward way of determining whether any changes you introduced broke existing functionality---especially important if you were to be extending the Markdown syntax, for example. ### Benchmarks (2m) Finally, we have benchmarks. These let us tell how *fast* something runs. One of the most common places we see benchmarks employed is comparing competing libraries. Far more usefully, though, if there is a performance-critical section of your code, you can use this to make sure that changes you make don't cause things to slow down. To return to that Markdown-parsing example, *both* of these would be useful. If your library can parse Markdown twice as fast as any other Rust implementation, that really is useful for people to know. But at least as important, if you decide you want to add footnote support, rather than just supporting the original footnote-less syntax, it's extremely helpful to know whether the additional syntax-checking you do has a serious impact on the speed of your code. If you suddenly take twice as long to parse a document because you're checking for footnotes, you know that you've probably done something wrong in your implementation, and it will help you find what and where. Benchmarks are currently behind a feature flag, which also means that they're only available on nightly Rust release. Using a nightly build, you can do benchmarks by adding the `#[feature(test)]`, and then adding the `#[bench]` to a function definition, and adding a special argument---a mutable reference to a `Bencher` type. Within the body of the function, you call the `iter` method on the `Bencher` instance with a closure taking the functionality you want to benchmark. Then when you run **cargo bench**, you will get benchmark results for that particular functionality. Handy! Closing (1m) ------- Next time, we'll take an introductory look at Rust's generic types and its `traits`, which are the foundation of really expressive programming Rust. I say "introductory" because I expect a full discussion of those concepts first of all to take more than one week and secondly to be a bit beyond me yet! ### Sponsors Thanks to Chris Palmer for sponsoring the show this month! See the list of other sponsors in the show notes. If you'd like to sponsor the show yourself, you can set up recurring donations at Patreon.com/newrustacean, or one-off donations at Venmo, Dwolla, or cash.me. ### Follow/support You can find show notes with detailed code samples illustrating these ideas, as well as links to things mentioned on the show, at NewRustacean.com. You can also follow the show on Twitter or App.net @newrustacean, or follow me there @chriskrycho. If you like the show, please rate and review it on iTunes to help others find it. Last but not least, I'd love to hear from you on social media, in the thread for the show on the Rust user forum at users.rust-lang.org, or via email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e008-script.md ================================================ Just like something else ======================== Intro (15s) ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 8: Just like something else*. News (1m 30s -> 1m 45s) ---- Before we jump in, I apologize for the delay between episodes. Unfortunately, I've been sick! I was just getting over one cold, and then got another---and both seriously impacted my voice. But I'm back, and excited to be recording again. Next, a couple things that might be interesting to you. The first is the "This Week in Rust" project, which highlights interesting projects in the Rust community. You can follow it @ThisWeekInRust on Twitter or subscribe to their weekly email at this-week-in-rust.com. The second is for people interested in the high-level issues around implementing languages, compilers, and even operating systems, and indirectly related to Rust. Joe Duffy, the current director of Microsoft's compiler and language platform group, has been blogging about his experience working on a research project at Microsoft which involved a safe, highly concurrent language and OS, with a number of lessons learned from that project. Aside from calling Rust "just plain awesome," there's nothing directly related to Rust in the blog posts, but they're quite informative about how another group tackled some of the same challenges that Rust has been. Now, let's talk about generics and traits! Overview (2m 30s -> 4m 15s) -------- One of the most important lessons you learn writing software is "don't repeat yourself". Experience---often painful experience---shows that when you have the same code in more than one place, things will go wrong when you change it. And change is inevitable in software. So we always try to minimize repetition. This can be challenging when we're dealing with different types, though. Multiplying two floating point numbers isn't the same as multiplying two integers: at the assembly instruction level, you actually have to implement those differently, because you represent integers and floating point numbers differently. And in fact, these kinds of differences even crop up within individual kinds of floating point numbers. As a result, if you have a function that's designed to operate on 32-bit floating point numbers, you need a separate function to perform the same operation on 64-bit floating point numbers. This isn't just a theoretical problem: C, for example, has three functions in its standard library for calculating the power of a number: `powf`, `pow`, and `powl`, for `float`, `double`, and `long double` types respectively. In C, you *can* just use the `double` version, because the C compiler will implicitly convert a `float` to a `double`---but you shouldn't, and if you cast back to a `float` when you're done, you'll end up truncating the value. For that reason, Rust, with its much stronger types, *won't* make implicit casts like that. Good form is using the type-specific function. But doing that, whether in the standard library or in your own code, means having multiple versions of functions. And we don't want that. More than one implementation almost inevitably means introducing bugs when we make changes. We need a way to write functions---and other things, like types!---which can work more *generically*. And if you've used a language newer than C or Fortran, you probably have an idea of where we're headed. Generics (6m 45s -> 11m) -------- There are two basic ways of tackling this problem. In modern languages, including C++, Java, C♯, Swift, Python, Ruby, JavaScript, and so on, we have either *generics* or *duck typing*. (We might also talk about *interfaces*, but there we'd be getting ahead of ourselves.) In general, the decision to use generics or duck typing is at the language level: generics are the solution for statically-typed languages, while duck typing is the solution for dynamically-typed languages. Generics allow you to specify to the compiler that a given function can operate on more than one type. Rather than just the standard argument types for an integer, a string, a float, an enum or struct, etc., we can specify a *generic* parameter. Then we can call the function with any type which supports the operations executed by the function. For a trivial example, we could write a single `multiply` function which takes two arguments and multiplies them together. We don't need to deal with overloading the function definition with different type arguments---unsigned integers, signed integers, different sizes of floating point numbers, etc.---because the compiler can handle them under a single *generic* definition. You get a similar benefit from "duck-typing" in dynamically typed languages. The name "duck-typing" tells us what we mean: if it walks like a duck, quacks like a duck, swims like a duck, etc., it's a duck---or at least, close enough to being a duck for our purposes. To put it another way, as long as a given type has all the attributes we need to operate on it---data, methods, etc.---it's a valid parameter for a function taking a type which behaves in those ways. In a way, *all* function calls, and all container types, are inherently "generic" in dynamically-typed languages. That just falls out of dynamic typing. That's a big part of what makes dynamically-typed languages so productive. So if you want to increase the productivity of your statically-typed language, providing tools for generic programming is a big step. And of course, if you do provide tools for generics to statically-typed languages, you get the other usual benefits that come with that: getting your types wrong when you're trying to do something with a "generic" function or container in a dynamically-typed language---a.k.a., any function or container!---is a *run-time error*. In a statically-typed language with generics, it is a compile-time error instead. So, for example, in Python, if you pass a goose to a function that expects a duck, and the function calls the object's *quack* method, when you run the program you'll get an `AttributeError` telling you that the object simply doesn't *have* that method. Whoops. By contrast, if your generic code in Rust *compiles*, it will *run*. As always, this doesn't mean you can't introduce bugs. It just means you can't introduce that particular kind of bug. Small victories, right? Like in other statically-typed languages with generics---C++, Java, C♯, etc.---Rust marks generic types with angle brackets around the "name" of the generic type in function signatures or type definitions. By convention, a run-of-the-mill generic type just uses a capital 'T' there: 'T' for "type". If you have more than one generic, by convention you just keep cycling through the alphabet, 'U', 'V', etc. (Of course, if you make it to 'Z' in a given generic function definition, you should probably reevaluate your API design!) Exceptions to this naming scheme include times when it's handy to indicate something else about the type by using a different capital letter to represent it. For example, in Sean Griffin's Diesel library, an ORM and SQL query builder, he uses `R` to represent generic *row* types. In all of this discussion about generics, I've left two major points unstated, though. First, while we've limited our discussion so far to generics in *functions*, Rust and other similar languages allow us to define types themselves as generic. In fact, back in episode 3, I talked about two of the major examples of generic types in Rust: `Option` and `Result`. And, as it turns out, *lots* of foundational types in Rust are generic, including vectors, the `Box` type we use for heap allocation, and all the reference-counted types---lots of types. As the example of `Option` indicates, the type is generic *before* compilation, but after compilation it becomes a specific instance of that type. So you start with a generic `Option`, but you end up with an optional *string*, or an optional `i32`, etc. This is a process called "mono-morphization": the Rust compiler takes the "polymorphic" item---one which works over many types---and creates a concrete version at compile time, with a name specific to that version---one which works over only that one type. That's what gets compiled into your final executable. The second thing I left out is that while being generic is great, it's fairly obvious that we won't always want to be generic over *everything*. A function for multiplication probably doesn't make any sense to be generic over strings, or over random data structures we build. Actually, off the top of my head, I haven't been able to come up with a meaningful function which is actually generic over *all* types. (If you have an example, let me know!) Even a function which just prints a type's value isn't, strictly speaking, generic over all types. So how do we deal with this? Traits (5m 45s -> 16m 45s) ------ In any case, Rust gives us a way to address our need for boundaries on just how generic a function or type actually is: we call them `trait`s. And as it turns out, `traits` are also the Rustic way to share behavior between different types. If you've used a language like Java or C♯, you'll be familiar with the concept of *interfaces*. If you've used Python or Ruby, you're probably familiar with the idea of *mixins*. Interfaces and mixins respectively are the closest analogies in those languages to Rust's traits, but there are some very important differences we'll come to in a moment. Traits in Rust are a way of specifying that a given type has a given behavior---but, unlike polymorphism in a classical object-oriented type system, they're completely orthogonal to types. That is, you define traits separately from the types which implement them. Let's take an extremely common example: creating a string representation of a given data type. One way you might tackle this is by having all objects inherit from a base type, which includes a method defining how to print it. In Python, for example, all types derive from `object`, which has a private method called `__repr__`. When you call the `print` function on some object, Python calls the `__repr__` method on the object instance, and it hands back a string. There are lots of benefits to doing things that way, but it also limits you. If you want to include behavior from multiple different sources, you end up with multiple inheritance---usually via a mixin system. The other option in classical inheritance, and the one more common in statically typed languages like Java or C♯, is to have interfaces. In that approach, you define what methods must exist for a given object (something like a `toString` method) to conform to a given interface (which might be named `IPrintable`). Classes then specify that they implement that interface (usually via something like `implements IPrintable` on the class definition) and supply conforming method implementations. The big upside to mixins over interfaces is that you get the actual implementation, because you're actually inheriting the existing behavior---and of course, you can override it in a subclass as you need to. With interfaces, you have to reimplement the behavior on every class which uses the interface, which takes us back to our repeated-code problem. The advantage to interfaces, and the reason Java and C♯ prefer them over mixins, is that you don't run into the many, *manY* problems which come with multiple inheritance. Rust sidesteps this tension by stealing a page from Haskell's "type classes". If you remember from our early discussion of custom types in episodes 2 and 3, Rust doesn't define the implementation details where it defines the data representation. This might seem a little strange at first, but there's a good reason for it. By separating the behavior of the type from its data, we are able to extend that behavior arbitrarily. The `impl` blocks we supply for Rust types allow us to implement the interfaces specified by `trait`s elsewhere, as well as our own behavior. If we want an object to be printable, we just `impl` the `Display` trait for the type. (You can see an example of this in the source for this week's show notes.) This approach lets us define the behavior of types by *composing* different elements together, rather than *inheriting* down a linear (or diamond-shaped) chain. And while inheritance is powerful, and there are good reasons to include it in your programming language---the Rust team is actively exploring how inheritance might fit in the language---composition is *more* powerful. 1. It gives us the benefits of mixins: we can define default implementations, which types can override if necessary. 2. It gives us the benefits of interfaces: we can define the behavior which conforming types must implement, while not being bound by inheritance. Add in strong type guarantees, and this is fantastic. It gives us the ability to specify common patterns of behavior, and the same language machinery lets us constrain generics so we can say exactly what a given function or type is generic with respect to. For example, if we want to say that a function is generic over any type that implements Rust's `Display` trait---that is, any type which can be nicely printed---we can just specify that in the function signature: add a colon after the name of the generic and the trait name, like "T: Display", and you're off to the races. Closing (1m 30s -> 18m 15s) ------- That should give you a taste of the power of generics and traits. Next time, we'll move from this high-level discussion of traits to a discussion of what it looks like to use them in practice in Rust. We'll look at the different kinds of traits Rust offers, how we might combine them, and what some of the current limitations are. ### Sponsors Thanks to Chris Palmer for sponsoring the show this month! See the list of other sponsors in the show notes. If you'd like to sponsor the show yourself, you can set up recurring donations at Patreon.com/newrustacean, or one-off donations at Venmo, Dwolla, or cash.me. ### Follow/support You can find show notes with detailed code samples illustrating these ideas, as well as links to things mentioned on the show, at NewRustacean.com. You can also follow the show on Twitter or App.net @newrustacean, or follow me there @chriskrycho. If you like the show, please rate and review it on iTunes to help others find it. Last but not least, I'd love to hear from you on social media, in the thread for the show on the Rust user forum at users.rust-lang.org, or via email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e009-script.md ================================================ Composing a Rustic tune ======================= Intro (30s) ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 9: Composing a Rustic tune*. News (2m 30s -> 3m) ---- Things have been a bit quiet the last couple weeks---the holidays will do that! There are a couple tidbits of note, however. Nick Cameron, one of the Rust core developers, wrote an interesting blog post called "My Thoughts on Rust in 2016," which I'll link in the show-notes. It's thoughts and guesses, not promises, but it still makes for interesting reading. The one other pretty big piece of news, though it's a fair ways out yet, is a pair of breaking changes in the language coming in the 1.7 release. Both of the changes have to do with details in the type system which we haven't even talked about on the show yet, and both of the changes *improve* Rust's type system to make it more robust. One of these changes started issue warnings in 1.4 back in October 2015, and will become compile errors when Rust 1.7 comes out on March 3. The other will become warnings with 1.7 and errors at some later point. One of the neat things about this is how the Rust team has been able to tell before making the change how many packages will be affected by it and in fact to inform the package developers (and people who depend on them) of the issues. This all falls out of the tooling they've built over the last year, especially a tool called Crater which runs the compiler over every package uploaded to crates.io and sees what breaks with any given set of changes. As of the 1.5 release, they saw that 96% of the crates which compiled with 1.0 still compiled, which is a big deal for a language still being developed this actively. In any case, keep your eyes out for those changes coming in March. I'll link the forum announcement and the relevant RFCs in the show notes! Now, let's talk some more about traits! Overview (1m -> 4m) -------- Last week, we talked about both generics and traits, but at a fairly high level. This week, we're going to build on that by getting down into the nitty-gritty of what using generics and traits looks like in practice. There's not going to be much test code in the show notes this week. Writing enough code to be meaningful for this would be, well... a lot. Instead, I'm going to refer to the standard library docs, because they have a *ton* of generics and traits in them. In fact, a lot of what might feel like core behavior of the language is actually just standard library functionality, implemented in terms of generics and traits. `Iterator` (8m -> 12m) ---------- Let's start by talking about the `Iterator` trait, which is a perfect example of something that provides enormous functionality, but is just a trait---and, apart from the syntactic sugar that the compiler provides for using it, one you could write yourself. As an aside, if the main ways you've been working at learning Rust are through the Rust book, or Rust by Example, then you should definitely start digging into the documentation proper. In many cases, the standard library documentation includes not only definitions of the specific types and functions and methods defined in a given module, but also great information beyond what you'd find in the more tutorial-like walkthrough in the books. Those tutorials, like the show notes pages, link directly to the underlying source, as well, which is also extremely illuminating. ### `Iterator` I'll quote from the `std::iter` module to start, in fact: > The heart and soul of this module is the `Iterator` trait.... > > An iterator has a method, `next()`, which when called, returns an > `Option`. `next()` will return `Some(Item)` as long as there are > elements, and once they've all been exhausted, will return `None` to indicate > that iteration is finished. Individual iterators may choose to resume > iteration, and so calling `next()` again may or may not eventually start > returning `Some(Item)` again at some point. > > Iterators are also composable, and it's common to chain them together to do > more complex forms of processing. Let's break this down. The module itself is built on the `Iterator` trait. There are about 3700 lines of code in this module, including all the documentation, so that's a pretty substantial chunk of Rust's standard library dedicated to implementing and explaining this one trait. As it turns out, though, that's really helpful as an example for people *learning* the language: if core features of everyday Rust are built out of the underlying machinery this way, then we can come up with our own, equally powerful abstractions if we need them. (As an aside, this is exactly what's going on in things like the regex module, for example, which takes a number of pieces of core functionality, including macros, and builds a very sophisticated library out of it. You can see the same thing in any number of the other libraries out there.) Back to the iterator module docs. The next thing we heard is a description of one of the basic methods available to anything that implements the `Iterator` trait. All iterators have a `next()` method, and it returns an `Option`. If the iterator still has items in it, it'll be `Some(item)`; otherwise, if you've exhausted the iterator, it'll be `None`. This same behavior exists whether you're iterating over a vector, a string, a hash-map, a linked list, or quite literally *any other* data type which implements `Iterator`. Importantly, those types don't have to be "collection" types. To borrow a page from the _Rust by Example_ book, for example, you could implement a Fibonacci number generator in terms of `Iterator`, with `next()` always generating the next value in the sequence. (Because it's an infinite sequence, you'd never return `None`, always `Some(integer)`). Now, the `Iterator` trait also defines dozens---and I'm not exaggerating here, literally dozens---of other methods besides `next()`. But as we discussed before, you can supply default implementations for trait methods, and that's exactly what `Iterator` does. A great many of Rust's facilities for functional-style programming appear in the `Iterator` trait, so if you want to be using map or fold or any other such usual suspects from functional programming, `Iterator` is your source. ### Composition Wrapping up that description, the last thing I quoted was the assertion that iterators are *composable*. This is precisely why those functional patterns work so well: you can take one kind of iterable and create another one, and another, and in each case you can use the *exact same operations* on the resulting iterable type. Why? Because all iterable types have those methods defined on them---either from the defaults that `Iterator` itself supplies, or with a custom definition which overrides those defaults. So that's all great, but where it becomes really powerful is this: if you come up with your own custom data type, and it makes sense to iterate over it, you can implement `Iterator` on it by supplying a `next()` method, and you'll get all of that behavior for free. You can run `for` loops over your bespoke data type. For free. Moreover, if you want to put multiple traits together, you can. You'll see this all over the Rust standard library, and all over idiomatic Rust code in general. Defining a new type? There's a good chance you'll want to implement a bunch of traits for it---`Add` to add things, `Drop` to define custom destructor behavior when the item goes out of scope, equivalence via `PartialEq` or `Eq` depending on what kind of equivalence you have, ordering via `PartialOrd` or `Ord` depending on what kind of ordering your set supports... you get the idea. ### `[derive()]` I've skipped over this in previous episodes, but Rust also provides tools for implementing some of the more common traits automatically. If you think back to our discussion of attributes in episode 7, you'll recall that I mentioned being able to "derive" the `Debug` attribute. Well, what's actually going on there is that `Debug` is a trait, and the Rust compiler is smart enough to know what a normal debug representation of many data types is, so we can get that for free instead of going through the tedium of implementing that trait over, and over, and over again. In fact, *many* built-in traits can be "derived" this way, which lets you create quite sophisticated behaviors around your custom types without needing to do the heavy lifting yourself except for the places your type *differs* from the baseline. In short, we get some really powerful abstractions, allowing us to create sophisticated behaviors around even complex custom types, just by composing different traits together---but we're not paying a cost at runtime for it. It all comes at compile-time. Neat! Syntax (4m -> 16m) ------ Let's talk about `trait` syntax for a minute. Precisely because composition of traits is the main way we define complex types in Rust, the syntax is a bit less verbose than for interfaces in languages like Java or C#. Instead of an `implements` keyword, we can simply include the name of the trait bounds we specify on a given generic immediately after it. If we are generic over a type T which implements the *add* trait, we'd spell that `T: Add`. We can also use the `where` clause to do this. You can think of `where` clauses as a way of spreading things out a little so that your type signatures, especially for complicated functions, don't make your eyes explode. Instead of annotating the generic bounds where they are defined, you can define them later. So you might define a generic type `T` in your function definition, and at the end of the definition---after the arguments, but before the curly brace which opens the function body---you would include `where T: Add`. This isn't a big deal where you only have one argument with one trait applied, but it becomes quite useful if you have multiple arguments which have to conform to certain trait constraints. What about defining a new trait? It's about as you'd expect: you simply write `trait` followed by the name of the trait, and then the usual curly-braces to mark off the body of the `trait`. If the body of the trait is empty, it's what we call a *marker trait*. You can use these to say, "This can be used in a specific context" when that context doesn't require given functions to be implemented. The Rust book gives the example of the `Send` trait, which indicates that it is safe to send a given type between two threads. That doesn't require a function, but it *does* require you to make sure that the type is memory-safe in certain ways! Limitations (1m -> 17m) ----------- As powerful as all these tools are, Rust's traits can't do everything. And specifically, as of today you can't implement the same trait in a more specific way if it makes sense for a given type if there's already a concrete implementation in place. This is a serious blocker for some kinds of optimizations, and fixing it would lay the groundwork for a Rustic approach to inheritance, which would be a nice addition to the language (even if we still think composition is better in most cases). I'll link that RFC, as well as a helpful blog post by the RFC author, to the show notes. That way you can take a look if you're interested in some of the language design issues and their ramifications for you as a developer. Closing (2m 30s -> 19m 30s) ------- A little teaser for the future: you can actually act on what are called *trait objects*, where you provide a reference to the name of a trait as shorthand for a reference to *some object which implements that trait*. When you do this, you end up with *runtime* resolution, rather than *compile-time* resolution. In other words: dynamic dispatch. We'll leave aside the details for now, but it's helpful to know it's out there. If you see a function returning a boxed up trait you'll know what you're seeing. There's also an open RFC to act on trait objects in general, which will further expand the utility of traits and of generic programming in Rust in some neat ways. Next time, we're going to talk about something that will sound awfully familiar but prove extremely unfamiliar to you if you've spent a lot of time in C or C++: Rust's *macro* system. ### Sponsors Thanks to Hamza Sheikh and Chris Palmer for sponsoring the show this month! Check out the list of other sponsors in the show notes. You are all amazing; I really appreciate your support as I make the show. (So does my wife!) If *you'd* like to sponsor the show, you can set up recurring donations at Patreon.com/newrustacean, or one-off donations at Venmo, Dwolla, or cash.me. ### Follow/support You can find show notes with detailed code samples illustrating these ideas, as well as links to things mentioned on the show, at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you like the show, you'd make my week by rating it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend! Thanks to everyone who's added corrections and fixed typos in the show notes; pull requests are great. I also love hearing from you! Definitely say hi on social media, add your thoughts in the thread for the episode on the Rust user forum at users.rust-lang.org, or shoot me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e010-script.md ================================================ Macros rule! ============ Intro (30s -> 0:30) ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 10: Macros rule!* News (1m 30s -> 2:00) ---- A couple items of interest from around the Rust community: - Julia Evans has a great set of slides titled "Why I (Heart) Rust" which was a ton of fun and has a really delightful art style to it. She also has a series of blog posts about writing a small operating system in Rust. Those posts were back in 2014, well before the language stabilized, so there are a bunch of things which have changed since then, but they're still quite interesting. - Speaking of operating systems, Rust community coordinator Steve Klabnik has started a project call IntermezzOS, which a small teaching operating system built in Rust. It specifically focuses on (and I quote from the landing page), "introducing systems programming concepts to experienced developers from other areas of programming." For my part I'm hoping to play with IntermezzOS here and there over the next few months, just because I'd like to learn some of those pieces myself. For today, though, let's talk about something totally different: macros! Overview of macros (2m -> 4:00) ------------------ So far, we have focused entirely on what I would call the more "normal" features of Rust. Even though there have been some substantial differences between Rust and other languages you might know because of its type system, most of the things we've done are still pretty familiar. Today's topic takes into a bit stranger territory, though. Today we're talking about *macros*, which are Rust's way of providing ways of transforming your code apart from the usual suspects of functions. I said "transforming your code" because macros actually working on the abstract syntax tree that makes up the result of the Rust compiler's first pass on the source you hand it. When you define macros, you actually *transform* that syntax tree into a *different* syntax tree. Rust has two kinds of macros today: the transformations we'll be dealing with today, which we might call *syntactic* macros, and compiler plugins, often called *procedural* macros. There are also plans for dramatic improvements to the syntactic macro system in the future, which I'll come back to and talk about a little bit at the end of the show. There are two reasons I'm focusing on substitution macros today: 1. They're way easier to deal with, and I understand them *decently* well---at least well enough to use them a little here and there, and to explain them decently. I can't say the same for compiler plugins, which let you run arbitrary code in the compilation phase! That's still a bit beyond me. 2. They're *stable*. Compiler plugins presently only work in nightly Rust. The language development team *is* interested in making that functionality available to everyone... eventually. But they're still thinking about the best way to do that, and until they have a solution everyone is comfortable with, they're not going to stabilize it, precisely because of the guarantees Rust makes about stability. So for now, we'll just stick with the simpler substitution macros, which are stable and a bit easier for regular Rust developers to pick up and understand. Macros by Example (13m 30s -> 17:30) ----------------- ### Discussion (4m 30s -> 8:30) Properly speaking, we call these substitution macros "macros by example" after the paper which formulated them back in the eighties; I'll link it in the show notes. Fair warning: it's heavy on parentheses, because it came out of Lisp, and on math. In any case, the macro's own body defines how the substitution behaves. Rust's macros are not running *arbitrary* changes on the syntax tree; that's limited to the compiler plugin approach. Instead, they're a fairly sophisticated way of doing *syntax substitutions*. If you're familiar with preprocessor macros in C and C++, you can think of these macros-by-example as being like those---only much more powerful *and* way safer. Another important distinction: in C and C++, preprocessor macros are exactly what they sound like: *pre*-processing. They transform the *text* in the source code, before any compilation occurs. And that's *all* they do in terms of transformations: they substitute one set of text for another. In Rust, macros-by-example are instead an early part of the compilation process proper, and they don't operate on *text*; they operate on the *abstract syntax tree*. Another analogy would be to the text transformations you can accomplish with a sophisticated regular expression engine---but again, operating on syntax instead of on text elements. This difference---that they operate on the *abstract syntax tree* rather than on the strings in the source code, is the reason that Rust's macros are so much more powerful and so much safer than C or C++'s. You can perform macro substitutions on items, blocks, statements, patterns, expressions, types, identifiers, paths, the sides of the fat-arrow operator (like the one used in `match` arms), and attribute contents, and of course you can mix and match those as you like. The big takeaway here is that you're transforming an abstract representation of the syntax. You can certainly write bugs in your macros, and because of how macro processing happens, they can be non-trivial to chase down. But---and this is a big deal---you cannot do things like clobber local variable names! One of the most common mistakes people make when writing macros in C or C++ is forgetting that it's just simple text substitution. If you use "x" in your macro in C, and there's a local variable named "x" someplace where you use that macro, those two things *are the same variable* when all is said and done, regardless of what you intended. There are lots of ways people get around that---naming, wrapping things in blocks, etc.---but they all derive from the fact that you can only transform the *text of the source code* there. Since that's not what we're doing in Rust, and because the macros are implemented with the notion of "syntax context," we get a wonderful property called "hygiene." If you define what seems like it should be an ordinary local variable in a Rust macro, it *is* a normal local variable; it doesn't clobber the names in use wherever the macro is applied. Thus, you can *safely* use normal names, without worrying that you're accidentally shadowing and potentially blowing away the values in some existing variable. The combination of *syntactic substitution* with *hygiene* lets us write powerful, safe macros which can make for much more readable code. Let's make this concrete by looking at some examples of macros in the Rust library, and then we can look at what's involved in building your *own* macros. ### Some built-in macros (3m 30s -> 12:00) Okay, so now we have some idea what we're talking about with macros, but how do we actually use them in Rust? And how do we build our own? Using macros is basically like using a function, with two significant differences. One, all of these macros have an exclamation point after their name when you're using them. For example, the most common macro you'll run into is probably the *try* macro, which you write `try!`. And of course, if you've looked at almost any of the example code I supply with the different episodes, or with any other Rust tutorials or documentation online, you've probably already seen a bunch of other common items: I've used the `println!` macro heavily, and once we got into the test code I started using the `assert!` and `assert_eq!` macros, which both make use of the `panic!` macro under the covers. So I'll offer some brief comments on each of these, as they're among macros you'll see most often in Rust. - The `try!` is used for dealing with `Result` types conveniently. Imagine a function where you want to do a bunch of file operations, each of which can fail, and which accordingly return `Result`s. Every time, you want to return a `Result` from your own function if there is an `Err`, and continue if the operation succeeded: you don't want to try to write to a file if you didn't get back a file pointer, for example. Instead of writing `match` expressions for every `Result` in the function, you can just wrap them with `try!`, which does exactly that---but makes your own code way easier to read. (Note: you can't use the regular `try!` in `main()` because `main()` doesn't return a `Result`. But one of the example in the show notes this week is a version of `try!` which works in `main()`!) - The `print!`, `println!`, `write!`, `writeln!`, and `format!` are convenient wrappers around string formatting and printing or writing to buffers. `format!` is used by all the others to supply string formatting like you'd see in C's `printf` or Python's `str.format`. The *print* and *write* macros provide convenient ways to call the `std::io` module's functions for printing and writing to buffers, with format operations applied first. - The `assert!` and `assert_eq!` macros are usually used for testing; they let you test general boolean expressions and equality of values respectively. If they fail, they use the `panic!` macro internally. - The `panic!` macro is for unrecoverable, unexpected errors. You can think of it *kind of* like an exception you *can't* catch in another language. It causes a thread panic, which unravels the stack and dumps it to stderr. You shouldn't see these very often, but they are appropriate from time to time. ### `macro_rules!` (2m -> 14:00) What about *writing* macros? You create a new macro with (wait for it)... a macro! The macro-by-example macro-creation macro is called `macro_rules`. You write it like any other macro: "macro-underscore-rules-exclamation-point". It is used as a standalone item, rather than in the midst of a function or expression like those discussed above. (Of course, other macros can be written that way as well, and it may make good sense to do so, depending on the kind of macro you're writing.) So for example, in the show notes for this episode, I defined two macros so you can see how they work. One is them is the variation on `try!` that works in `main()` functions which I mentioned earlier. The other example macro I wrote takes any identifier---a variable, a function, a type, etc.---and prints a little message including its name. That second macro shows how macros can use other macros, and in fact you can have recursive macro usage. (Good luck debugging those, though! It's possible, but it's a lot of work.) I actually came up with the idea for that `main_try!` when helping a friend get going with Rust a few months ago, and discovered that it's not hard to write some simple macros in Rust. I ended up needing to write a similar shortcut in some C++ I was working a few weeks later, and let me just say: it's definitely easier to write a macro without shooting yourself in the foot in Rust than in C or C++. ### Downsides (1m 30s -> 15:30) It isn't all sunshine and roses, though. Macros are powerful, but they are a secondary tool, not the first thing you should reach for. As the Rust book says: > The drawback is that macro-based code can be harder to understand, because > fewer of the built-in rules apply. Like an ordinary function, a well-behaved > macro can be used without understanding its implementation. However, it can be > difficult to design a well-behaved macro! Additionally, compiler errors in > macro code are harder to interpret, because they describe problems in the > expanded code, not the source-level form that developers use. > > These drawbacks make macros something of a "feature of last resort". That’s > not to say that macros are bad; they are part of Rust because sometimes > they’re needed for truly concise, well-abstracted code. Just keep this > tradeoff in mind. In general, you should use the more standard language machinery: functions, types, and traits. When you need them, though, macros are around, and they're pretty great. ### Limitations and upcoming changes (2m -> 17:30) There are a few things that macros can't do, or can't do well, even with everything we talked about above. First, you can't use a macro in arbitrary locations in code. You can't use them as the field in a struct, or as a trait item, for example, because of how the compiler parsing sequence unfolds. Another limit is that hygiene---that nice property that means we don't stomp all over existing names, etc.---isn't fully fleshed out. It's better than in C or C++ by a mile, but it doesn't apply to types, or lifetimes, so it still has some places where it can throw a wrench into things. There are also some quirks around macro names, because they don't get the same namespace treatment that normal types, etc. do. (You can actually see this in play in the show notes, where they don't end up in the module for this episode, but in the crate at the top level.) And, annoyingly and unlike the rest of Rust, the order you define them in matters! You can get around a lot of these issues to varying degrees, but the limitations are still frustrating. For a much more detailed discussion of these issues, you should see Nick Cameron's series of blog posts on macros, which I'll link in the show notes. You can also read about some of his plans for a proposed new, better approach for macros that would stabilize the procedural macros we skipped over today, as well as fixing a bunch of these issues along the way. Closing (2m -> 19:30) ------- A quick heads-up: this coming week, I'll be traveling to start a new job, and probably won't have a lot of extra time, so you can expect either a bonus episode or no episode next week. I have a short episode I'd *like* to do, and which I'm hoping I'll be able to knock out next weekend after I get back, but it depends on just how wiped out I am after traveling! ### Sponsors Thanks to Hamza Sheikh and Chris Palmer for sponsoring the show this month! You can see a full list of sponsors in the show notes. If *you'd* like to sponsor the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at Venmo, Dwolla, or cash.me. ### Follow/support You can find links to each of those, to other things mentioned on the show, and notes and detailed code samples illustrating macros at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. You can help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend! Thanks to everyone who's added corrections and fixed typos in the show notes; pull requests are great. I also love hearing from you! Definitely say hi on social media, add your thoughts in the thread for the episode on the Rust user forum at users.rust-lang.org, or shoot me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e011-script.md ================================================ Once upon a type ================ Intro {>> 30s → 0:30 <<} ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 11: Once Upon a Type*. Updates {>> 1m 30s → 2:00 <<} ------- The last month has been an unusual mix for the show, with a bonus episode about building community and then the two part interview with Sean Griffin, which I hope you all enjoyed! I got several requests for further interviews, and I already have a few in mind. My goal will be to release one every other month or so. A bit of news from the Rust community: Rust 1.7 came out this week! It included a bunch of standard library improvements, as well as the warnings for some type system soundness changes that were introduced back in 1.4 becoming errors. One of the highlighted standard library changes was a pretty substantial improvement to the way hash maps in the language behave, which can result in a serious speedup in a number of scenarios. The actual change was that you can now drop in a substitute algorithm for hashing, indicated to the compiler simply by specifying a generic. As it turns out, this leads right into our discussion for today! We're diving back into the more standard fare with an in-depth discussion of one of the things that Sean Griffin and I talked about a fair bit in our interview, and which has come up in the show incidentally from the beginning: Rust's type system, *as a type system*. Type systems {>> 9m 30s → 11:30 <<} ------------ Before we can talk about Rust's type system in particular, though, we have to answer a much more general question: What *is* a type system? And what do we mean when we talk about the different kinds of type systems programming languages have? We can come at this from two directions. One is in terms of the mechanics of programming and generating some runnable output form the computer. In that sense, our type system is the way a programming language has for representing data and functions to the compiler. We might distinguish between different type systems, then, in the extent to which they provide more or less information both to the computer and to the programmer. At the most basic level, there are bits---but we need a way to specify what those bits represent when we're running a program, and we need ways to tell the compiler or interpreter how it should think about those bits. It may actually help to come at it in much more abstract terms. A paper I read, which was a distillation of an opening lecture to Ph.D. students, put it this way: a type system is "a system describing what things can be constructed" ([source](http://www.cs.ru.nl/~herman/PUBS/IntroTT-improved.pdf)). That's helpful, and it explains what we mean when we start talking to the compiler. We are specifying *what to construct*, and *how to construct it*. For example, we might be constructing a number or a string, or a linked list, or a hash map. We also might be constructing a complex data structure with other data structures embedded in it. But we might also be constructing operations on those data types. We might be building a function which takes in two numbers and does something with them, or one that takes in any type which is iterable and iterates over all it's elements and prints them. We might build a function which takes an inter able and a function and calls the function argument in every item of that iterable. And so one. We tell the computer what we want to construct, and how to construct it. So type systems let us specify *intent* about our programs. ### The strong/weak and static/dynamic axes Now, there is enormous variation in the kinds of type systems out there. We might think about two major axes of type systems: static vs. dynamic, and strong vs. weak. By "static" vs. "dynamic" what we really mean is whether the types are known at the time of some compilation step---"static"---or only at runtime---"static". By "strong" vs. weak, we mean: how easy is to to transmute one type into another? In a strong type system, you have *strong* guarantees that an item with a given type will continue to be handles as that same type. In a *weak* type system, by contrast, the language might perform implicit conversions between types. On both of these axes, there are tradeoffs, and of course even though these two axes aren't directly connected, the *combinations* make for tradeoffs, too. Let's make this concrete in terms of languages you're probably familiar with at least in principle: - PHP is *dynamically* and *weakly* typed. (So is JavaScript.) Types are not known till run-time, and they can *and will* be implicitly converted. If you add an integer to a string, the language will just transform them under the covers so the operation makes sense. - Python is *dynamically* and *strongly* typed. Types are not known till run-time, but types are *not* implicitly converted. In the integer and string addition example, Python will throw a `TypeError` and tell you that addition isn't supported for the two different types. - C is *statically* and *weakly* typed. It's types are known at compile time, but it's trivial to coerce from one type to another. If you declare an integer and a character array string, and add them together, you'll get nonsense, but no compiler error. Granted: modern compilers will usually warn you about this, but that's no part of C itself. - Rust is *statically* and *strongly* typed. It's types are known at compile time, and there is no implicit conversion between types. You can convert between types, but you have to explicitly define the underlying transformation yourself, and explicitly call that transformation in your code, or it simply won't *compile*. So far so good. Type systems give us the ability to specify our intent to the computer, and have that intent enforced more or less rigorously. Dynamically typed systems are often more convenient, especially for rapid development, as they let you just write the code without worrying about specifying everything about the types. (In practice, once you're out of the rapid prototyping phase, you usually end up specifying *something* about the types, albeit usually in documentation, because if your function needs an iterable and you hand it something else, you'll get a runtime error. That's the attraction of a static type system, which can give you that information at compile time---but at the cost of making you spell everything out, which can slow you down considerably and can make rapid prototyping much harder.) Historically, most statically typed languages forced you to declare types fully whenever declaring an instance of the type: `Integer I = 5;` or `MyType someInstance = new MyType();` and so on. In languages descended from or inspired by ML, including Ocaml, Haskell, Swift, F^♯^, and Rust, a fair bit of the pain involved with specifying types ahead of time is removed because the compiler can often *infer* the types, and in far more sophisticated ways than you get even with C++'s `auto` or C^♯^'s `var` keywords. I'm not going to cover all the details of the Hindley-Milner type inference algorithm used by Haskell, F^♯^, and Rust---I don't understand it well enough, for one; and for another, it would take quite a while even if I did!---but suffice it to say it's enormously capable. This lets us have *strong*, *static* typing with a little bit less of the pain we might expect coming from other languages. ### The expressiveness axis So that gives us a pretty good idea about the static-vs.-dynamic and weak-vs.-strong axes. There's another axis, though, and that's what we might call "expressiveness": what kinds of concepts is your type system capable of communicating? While Rust is only a little stronger than Java, and probably about the same strength as C^♯^, it's more *expressive* than either. It can communicate things that they can't. Likewise, Haskell's type system is even more expressive than Rust's; it has concepts like *type constructors*, or *higher-kinded types*, which let you do generic things with types themselves. Beyond Haskell, there are yet further things you can express in type systems---things like so-called "dependent types", where the type of something can even include the specific values involved. If you're not tracking with that, it's okay: suffice it to say that there is an enormous range of "expressivity" and that Rust falls toward the *more* expressive end of it. But of course, there are tradeoffs here, too: the more your type system is capable of expressing, the more possibilities there are for getting things wrong in a variety of ways, and the more work you have to do to get the types you actually do want in place. (This is why type inference is such a big deal, in fact: if you had to fully write out every type in a language like Rust, much less Haskell, it would be incredibly annoying.) Examples {>> 6m 15s → 18:15 <<} -------- All fine in principle, but what do we actually mean by this? What's something you can express in Rust that you *can't* express in one of these other languages? Or even which is just much *harder* to express there? ### Enums Here's one we've covered in substantial detail already: Rust's enumerated types allow you to express, concisely and in one place, something which is perhaps *possible* in C or Python or C^♯^---you can make something that behaves roughly like a discriminated union in any of those languages---but which is both unnatural and nearly or actually impossible to get the guarantees around that Rust gives you. This is why error-handling in those languages ranges from just returning an error code (in C) to exception-based handling in Python and C^♯^. In none of those languages is there integrated, language-level support for returning a type which is *always* either a usable result or an error, with the details of the result or the error immediately available. In none of them can you force the caller to deal with the possibility of an error there, either. This is something that is straightforward to express in Rust, and difficult to express and impossible to enforce in those languages. That doesn't make them *bad* languages; each is very good in its own way. The point is simply that Rust's type system allows you to express a *concept*---the result of some operation---in the form of a *type*---specifically, the `Result` type. ### Higher-order functions Likewise, in Rust you can tell the compiler not only that you expect a function as an argument to another function, but what *kind* of function you will take as an argument. You can say, "This function accepts functions which operate on all iterable, addable types," for example. Or, further, "This function accepts a function which itself takes a function acting on a given type as an argument." This kind of thing hurt my head at first, but it's incredibly powerful. And unlike in, say, JavaScript (where that kind of things is are also incredibly common), here we can know ahead of time whether we're meeting the required interface. We can express our intent to the compiler through the type system, and the compiler can then respond if we try to pass in a function which doesn't correspond to the relevant type requirements. ### Lifetimes For one last example, one of the things we haven't talked about on the show yet---lifetimes---is both a part of Rust's type system *and* something that it's really nice that the compiler can usually infer for us, because they're hard. Having them available is an important part of Rust's memory-safety guarantees: knowing how long some piece of data lives lets the compiler, and specifically the borrow checker, make the right decisions about whether a given piece of data is available or not. But if we had to specify the lifetime of every single type, that would make our code much noisier, and much harder to write. Not just because it would involve more typing, but because we'd have to be *thinking* about it constantly. (I'd go so far as to say that if we had to write lifetimes everywhere, the benefit we get from tracking them wouldn't be worth the cost of using them in the vast majority of programs.) But lifetimes are also something you can express in Rust that you literally cannot express in many other languages. They *exist* in other languages, but that doesn't mean you can inform the compiler of your intent about them. This is directly analogous to the way that arguments to functions *exist* in Python: at run-time, some argument will be a string, or an integer, or some type you've constructed, but you have no way to tell Python that the type *must* be a string, or an integer, or some other type you've constructed. In a language like C++, you even have to reason about lifetimes, because like Rust, it does some deallocation of data behind the scenes for you when it can. But in Rust, you basically never have to call a destructor explicitly in code that *uses* a type, because all of those details are handled by lifetimes---and you can specify the lifetimes yourself as necessary, and the compiler will tell you when there's something wrong with the lifetimes. Don't get me wrong: as we'll talk about within the next few episodes, reasoning about, and informing the compiler about, lifetimes is still hard. But in Rust, we *can* tell the compiler about it. And any given piece of data in the language has a lifetime associated with it. So we can now *express* in the types themselves something we have to deal with in C++ separate from the type system (by calling destructors, and so on). Conclusion {>> 2m 30s → 20:45 <<} ---------- Coming back around to our opening, what does this have to do with the `HashMap` changes? Well, simply put, the *type* of a HashMap implementation is generic; so you can specify in the type system itself how a HashMap behaves, as long as you supply it a hashing algorithm that conforms to the specified bounds on that generic. If you write a new hashing algorithm tomorrow, as long as it meets those bounds, you can drop it in and go and *know* that it will work---barring logic bugs, etc.; but you won't get *run-time* errors because of missing items in types, functions not fulfilling contracts, etc. That's powerful! In the next episode we'll take a look at another interesting dynamic in Rust: that it is an expression-oriented language. That episode will include a fair number of specific code examples, as well, because it's much easier to illustrate in practice than *type systems in general*. ### Sponsors Thanks to Hamza Sheikh and Chris Palmer for sponsoring the show this month! You can see a full list of sponsors in the show notes. If *you'd* like to sponsor the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at Venmo, Dwolla, or cash.me. ### Follow/support You can find links to each of those, to other things mentioned on the show, and notes and detailed code samples illustrating macros at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. You can help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend! Thanks to everyone who's added corrections and fixed typos in the show notes; pull requests are great. I also love hearing from you! Definitely say hi on social media, add your thoughts in the thread for the episode on the Rust user forum at users.rust-lang.org, or shoot me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e011-transcript.md ================================================ New Rustacean 11 Transcript by @jeremywsherman hello, I'm Chris Krycho, and this is the New Rustacean podcast, a fifteen to twenty-minute show about learning the Rust programming language. This is episode 11: Once upon a…type? The last month has been an unusual mix for the show, with a bonus episode about building community, and then a two-part interview with Sean Griffin, which I hope you all enjoyed. I got several requests for further interviews, and I already have a few in mind. My goal will be to release one every other month or so. A bit of news from the Rust community: Rust 1.7 came out this week. It included a bunch of standard library improvements, as well as the warnings for some type system soundness changes that were introduced back in 1.4 becoming errors. Keep an eye out for that if you're upgrading. Many people will not be affected, but depending on the particulars of your implementation details, you might. One of the highlighted standard library changes was a pretty substantial improvement to the way hash maps in the language behave, which can nicely result in a serious speedup in a number of scenarios. The actual change underlying that was that you can now drop in a substitute algorithm for hashing, indicated to the compiler simply by specifying a specific type on the generic. As it turns out, this leads right into our discussion for today. We're diving back into the more standard fare for the show with an in-depth discussion of one of the things that Sean and I talked about a fair bit in the interview over the last couple episodes, and frankly which has come up in the show from the beginning: Rust's type system as a type system. Before we can talk about Rust's type system in particular, though, we have to answer a much more general question: What is a type system, and what do we mean when we talk about the different kinds of type systems that [2:00] programming languages have. We can come at this from two directions: One is in terms of the mechanics of programming and generating some runnable output from the computer. In that sense, our type system is the way a programming language has for representing data and functions to the compiler. We might distinguish between different type systems, then, in the extent to which they provide more or less information, both to the computer and to the programmer in that process. At the most basic level, there are bits, of course, ones and zeros down at the machine. But we need a way to specify what those bits represent when we're running a program, and we need ways to tell the compiler or interpreter how the should think about those bits. So it may actually help to come at that same question in more abstract terms. A paper I read, which was a distillation of an opening lecture to some PhD students, put it this way: A type system is "a system describing what things can be constructed." I think that's helpful: It explains what we mean when we start talking to the compiler, as we said above, we're specifying what to construct and how to construct it. For example, we might be constructing a number, or a string, or a linked list, or a hash map. We also might be constructing a complex data structure with other data structures embedded in it, and a hash map is just such an example ofttimes. But we also might be constructing operations on those data types. We might, for example, be building a function which takes in two number and does something with them, or one that takes in any type which is iterable and iterates over all its elements and prints them; we might build a function which takes an iterable and a function and calls the function argument on every item of that iterable, and so on. [4:00] We tell the computer what we want to construct and how to construct it. So type systems let us specify intent about our programs. They let us tell the compiler what we mean. Now, there is enormous variation in the kinds of type systems out there. We might think first about two major axes of type systems, the ones that come up most commonly in discussion I think: Static versus dynamic and strong versus weak. By "static versus dynamic" what we really mean is whether the types are known at the time of some compilation step, in which case they're static, or only at runtime, in which case they're dynamic. By the strong versus weak comparison we mean, how easy is it to transform, to transmute, one type into another. In a strong type system, you have strong guarantees that an item with a given type will continue to be handled as that same type. In a weak type system, by contrast, the language might perform implicit conversions between types. On both of these axes, there are trade-offs. And, of course, even though these two axes aren't directly connected, their combinations make for trade-offs, too. Let's make this concrete in terms of languages you're probably familiar with, at least in principal. PHP and JavaScript are both dynamically and weakly typed. Types are not known 'til runtime, and they can and will be implicitly converted. If, for example, you add an integer to a string, the language will just transform them under the covers so the operation makes sense and can be carried out. Whether that's exactly what you had in mind or not, that's what will happen. Python is dynamically and strongly typed. Again types are not known 'til runtime, but types are not implicitly converted. If you try to add an integer and a string together in Python, you will get a type error, and the interpreter will tell you [6:00] that addition isn't supported for the two different types. But again, that won't happen 'til runtime, it will not happen in some compilation step. C is statically typed but weakly typed. Its types, that is, are known at compile time, but it's trivial to coerce from one type to another. If you declare an integer and a character array string and add them together, you'll get nonsense, but you won't get a compiler error. Now, granted, modern compilers will usually warn you about that kind of thing, but strictly speaking, that's not part of C, that's tooling we've put around C because C's weak typing is known to be a problem. Getting back to home as it were, Rust is statically and strongly typed. Its types are known at compile time, and there is no implicit conversion between types. You can of course convert between types, but you have to explicitly define the underlying transformation yourself, and, in most cases, you have to explicitly call that transformation in your code, or it won't compile at all. Thus, in the integer and string addition example, if you don't have a defined transformation from integer to string for concatenation, or from a string to an integer for addition, Rust won't even compile it, and Rust won't compile it if you don't make that conversion explicit. So far so good: Type systems give us the ability to specify our intent to the computer and have that intent enforced more or less rigorously. Dynamically typed systems are often more convenient, especially for rapid development, as they let you just write the code without needing to specify everything about the types upfront. In practice, of course, once you're out of the rapid prototyping phase, you usually end up specifying something about the types, but that usually ends up in documentation, because if, for example, your function needs an iterable, and you hand it a non-iterable item, you will get a runtime error, [9:00] and that's a problem. That is the attraction of the static type system, which can give you that information at compile time. But of course it comes at the cost of making you spell everything out, which can slow you down considerably, and therefore can make rapid prototyping much harder. Now, historically, most statically typed languages forced you to declare types fully whenever declaring an instance of the type: An integer i equals five, or my type, some instance of that type, equals new my type, and so on. And all that ceremony can get old. In languages descended from or inspired by ML, however, including OCaml, Haskell, Swift, F#, and, to our concern, Rust, a fair bit of the pain involved with specifying types ahead of time is removed because the compiler can often infer the types, and in far more sophisticated ways than you get even with C++'s auto or C#'s var keywords. I'm not going to cover all the details of the Hindley–Milner type inference algorithm used by Haskell, F#, and Rust; I don't understand it well enough for one thing, and for another, it would take quite a while even if I did. But suffice it to say it's enormously capable. As a result, we can have strong, static typing with at least a little less of the pain we might expect coming from other strongly, statically typed languages. So that gives us a pretty good idea of the static versus dynamic and weak versus strong axes. There is another axis though, and that's what we might call expressiveness: What kinds of concepts is your type system capable of communicating? While Rust is only a little stronger than Java and probably about the same strength or, again, only a little stronger than C#, it's more expressive than either: It can communicate things that they can't. Likewise, Haskell's type system is even more expressive than Rust's: It has concepts like type constructors, or higher-kinded types, which let you [10:00] do generic things with types themselves. Beyond Haskell, there are yet further things you can express in type systems, things like so-called dependent types, where the type of something can even include the specific values involved. And if you're not tracking with that, it's okay; suffice it to say that there's an enormous range of expressivity, and that Rust falls toward the more expressive end of it, but not all the way at that end of it. But of course there are trade-offs here, too: The more your type system is capable of expressing, the more possibilities there are for getting things wrong in a variety of ways, and the more work you have to do to get the types you actually do want in place. This is why type inference is such a big deal: If you had to fully write out every type in a language like Rust, much less Haskell, it would be incredibly annoying. So that's all fine in principal, but what does it look like in practice? What is something you can express in Rust that you can't express in, say, C, or Python, or even that is just much harder to express there? Here's one example we've covered in substantial detail already: Rust's enumerated types, which allow you to express concisely and in one place something which is perhaps possible in C or Python or C# – you can make something that behaves roughly like a discriminated union in any of those languages, but it is both unnatural and nearly or actually impossible to get the guarantees around those that Rust gives you out of the box. This is why error handling in those languages ranges from just returning an error code or using a goto in C to exception-based handling in both Python and C#. None of those languages have integrated language-level support for returning a type which is always either a usable result or an error with the details of the result or the error immediately available there. Likewise, in none of them can you force the caller to deal with the possibility of an error at that site. [12:00] This is something that is both straightforward to express in Rust, and difficult to express and impossible to enforce in those languages. That doesn't make them bad languages; each is very good in its own way in fact. The point here is simply that Rust's type system allows you to express a concept – the result of some operation – in the form of a type: The Result type. Likewise, in Rust, you can tell the compiler not only that you expect a function as an argument to another function, but what kind of function you will take as an argument. You can say, this function accepts functions which operate on all iterable, addable types, for example, or further, this function accepts another function which itself takes a function acting on a given type as an argument. This kind of thing hurt my head at first, truly, but it's incredibly powerful, and unlike in, say, JavaScript, where I first ran into these ideas, and where they're also incredibly common, here in Rust, we can know ahead of time whether we're meeting the required interface. We can, through the type system, express our intent to the compiler, and the compiler can then respond if we try to pass in, say, a function which doesn't correspond to the relevant type requirements. For one last example, one of the things we haven't talked about on the show yet, lifetimes, is both a part of Rust's type system, and something that it is really nice that the compiler can usually infer for us because they're hard. Having them available is an important, essential even, part of Rust's memory safety guarantees. Knowing how long some piece of data lives lets the compiler, and specifically the borrow checker, make the right decisions about whether a given piece of data is available or not. But if we had to specify the lifetime of every single type every place we used it, that would make our code much noisier and much harder to write, not just because it would involve more typing, but because we'd have to be thinking [14:00] about it constantly. I'd go so far as to say that, if we had to write lifetimes everywhere, the benefit we get from tracking them probably wouldn't be worth the cost of using them in the vast majority of programs. But lifetimes are also something you can express in Rust that you literally cannot express in many other languages. They exist in those other languages, of course, but you can't necessarily inform the compiler of your intent about them. This is directly analogous to the way that arguments to function exist in Python. At runtime, some argument to a function will be a string or an integer or some type you've constructed, but you have no way to tell Python that the type must be a string or an integer or some other type you've constructed. In a language like C++, you have to reason about lifetimes, because, like Rust, it does some deallocation of data behind the scenes for you when it can, but in Rust you basically never have to call a destructor explicitly in code that just uses a type, because all of those details are handled for you by lifetimes, and you can as necessary specify the lifetimes yourself. And the compiler will tell you when there's something wrong with the lifetimes, it will just say, hey, you need a lifetime marker on this particular type. Don't get me wrong: As we'll cover in the next few episodes, reasoning about and informing the compiler about lifetimes is still hard. But in Rust, at least we can tell the compiler about it, and any given piece of data in the language has a lifetime associated with it, so we can now express, in the types themselves, something we have to deal with in C++ separate from the type system, by calling destructors or so on. Coming back around to our opening then, what does all of this have to do with those changes to the hash map? Well, simply put, the type of a hash map implementation is generic, so you can specify in the type system itself how a hash map behaves, so long as you supply it a hashing algorithm that conforms [16:00] to the specified bounds on that generic. ================================================ FILE: docs/e012-script.md ================================================ I'm not familiar with that expression ===================================== Intro {>> 15s → 0:15 <<} ----- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 12: I'm not familiar with that expression.* Updates {>> 2m 20s → 2:35 <<} ------- A few pieces of news from around the Rust community to kick things off: A project which has been going for a while but that just came to my attention this week is the *Redox* operating system. It's a Unix-like system which aims for broad but not total compatibility with Linux... and it's built entirely in Rust. I'm hoping to give it a whirl sometime this week and see how it goes, and the project is actively looking for contributors, so if that sounds interesting, you might check it out as well! Also of note, Mozilla announced this week that Servo, their research web renderer built entirely in Rust, will be shipping an alpha of a full web browser using the engine in June. That's *extremely* interesting because of some of the associated performance implications: the engine is written in Rust, and so it's simultaneously safe, fast, and parallelized. I'll link a video showing some pretty incredible GPU-powered web rendering the team has been doing, and which is, wonderfully enough, totally safe and also highly parallelized because it's written in Rust! Last but not least, Wired had a fascinating look at ongoing changes with Dropbox's cloud infrastructure this week, and one of the revelations was that the Dropbox team, which has made extensive use of Go and Python, now also uses Rust in their stack. As it turns out, Rust's combination of safety, performance, and low memory footprint made it a perfect choice for some of their most absolutely demanding software as they built their own cloud. It's a great read, so I'll link the article. It's fun to see Rust picking up more and more traction as we head on toward the one-year mark from the 1.0 release of the language! Now, into the meat of the show! An expression-oriented language ------------------------------- ### Overview {>> 1m 10s → 3:45 <<} One of the points I've frequently alluded to over the course of the show so far is that Rust is an *expression*-oriented language. Most of the other languages Rust superficially resembles---C, Java, Python, C++, C^♯^, PHP, JavaScript etc.---have in common that they are basically *statement*-oriented languages. Each of those languages, whatever its other strengths and weaknesses, treats *statements* as their base unit, so to speak---even when you add in substantial sophistication around objects, for example, you are still proceeding primarily by way of saying, "Do A. Then do B. Then do C," and so on. An unterminated expression is a compiler error in most cases in those languages---don't forget your semicolons! Rust, like many functional languages, treats expressions as a more core building block. To be sure, we have statements at our disposal. But as we'll see, in every corner of the language, expressions come to the fore. Let's look at three major examples of how this plays out in Rust: `if` expressions, `match` expressions, and `fn` expressions. ### `if` expressions {>> 3m 30s → 7m 15s <<} Many languages you may be familiar with have ternary expressions. In languages with C-like syntax, these are denoted by an expression that evaluates to a boolean, followed by a question mark, an expression whose value used if the boolean is true, a colon, and an expression whose value is used if the boolean is false. In Python, you have the expression for the true scenario, followed by *if* and the condition to evaluate, followed by *then* and the expression for if the condition evaluates to false. These are handy because they let you directly assign the result of the expression to a variable or constant. If you use a normal if statement in these languages, you have to assign the value within the body of that if statement and any alternative else or else-if clauses. With a ternary, you can skip that step, which is especially nice when dealing with languages where you have to declare the variable before assigning to it, as in C, Java, C^♯^, and so on. Rust doesn't have a special ternary operator or structure. It did, once upon a time, but it was removed. Why? Because it was completely redundant. *All* `if` blocks in Rust are expressions. An unterminated final expression in the block is treated as the value of the whole block, and may be assigned directly to a name. You might write `let foo = if bar { 42 } else { 3.141592653589793 };` and the value of `foo` would either be the answer to life, the universe, and everything; or a good enough approximation of pi for astronavigation. Again: the final expression of *any* if block is evaluated as the final *value* of that block. This will be a recurring theme. What about an if-block which concludes not with an expression but with a statement? That is, what if you just have a branch to carry out some varying sets of imperative logic depending on some condition? The if block still has a value: the empty tuple, sometimes called the unit type in various documentation posts. As it turns out, even statements in Rust have a type; it's just that the type of a statement is the empty tuple, the "unit type". That's basically a value-less type, but it's still a type. So the evaluated result of an if block which is just one or more statements is *also* just the empty tuple type. Of course, you're probably going to just ignore that value, as it's not very useful to you, and that's fine. (It would be kind of weird *not* to ignore it, actually.) The point is simply that even something that in other languages wouldn't be an expression at all, a statement, still has a type in Rust. ### `match` expressions {>> 1m → 8:15 <<} Essentially everything we've said about `if` blocks is equally true of `match` blocks. They aren't `match` *statements*; they're `match` *expressions*. Thus, you can assign the result of a `match` expression. So if you were matching on a boolean named `bar`, you could write `let foo = match bar { ... }` with the body having arms for the `true` and `false` cases, and simple values or a long complex block resulting in a final expression, or anything in between---but as long as the final element in the body of each match arms block is an expression, it'll be assigned correctly. And course, because of the strong types and good type inference Rust has, if you get mismatching types assigned this way, you'll get a compile error---and a pretty clear and informative one! ### Other block expressions {>> 1m 25s → 9:40 <<} These same things are true of generic blocks, actually. This means that you can treat all blocks as the expression they evaluate to, with an important caveat I'll get to in a moment. If you create a standalone block within a function, which you can do just by writing opening and closing braces, you can assign or return a final expression from that block just as you can from an if or a match block. Now for that caveat: this is strictly true, but it doesn't necessarily play out as you'd expect in loop constructs like `loop`, `while`, or `for`. Loop constructs *do* have an evaluated type and value, but it's always the unit type, the empty tuple. I strongly suspect that's because it wouldn't be especially clear or easy to reason about what the final expression value would be in loop constructs (especially with early breaks, which could lead to *very* weird syntax requirements to be able to specify the final value of the block). Still, this overall pattern---non-loop blocks evaluate to their final expression's value---opens up some very powerful ways of thinking about what our code does. ### `fn` expressions {>> 2m 30s → 12:10 <<} Before we get to that, though, let's take a minute to look at what is, at least to me, the most interesting consequence of that principle: that is, the way *functions* are evaluated as expressions. Note that functions are blocks, so they are evaluated as expressions. This explains a few things you've seen if you've looked at Rust code, and it also makes sense out of some things we've skipped over in earlier discussions on the show. First, the reason that you don't need a `return` statement at the end of a function to return a value explicitly (as you do in C, Java, Python, etc.) is because functions are expressions. Sometimes you'll hear or see people talk about this in terms of "implicit returns" and that may be technically accurate, but in my opinion that's not *really* the best way to think about it. Instead, just as with other expressions, the function evaluates to a value, and that value is the value of the final expression in the function (or the empty tuple/unit type, if you have a function with no return explicit return type). If you're thinking about it this way, the `return` keyword exists so that you can specify an early exit from a function and specify what the function expression's value should evaluate to at that particular location. Functions are just expressions like all other blocks, and `return` has the same kind of role in them that the `break` keyword and statement does in a `loop` construct. Second, thinking back to some of the things we looked at last week, this helps us understand how to think about the *type* of a function: it has a given set of inputs and has a specific type as its output. Even when we don't specify the return type, it still exists; it's just---implicitly---the unit type. And this is the bit which really provides a lot of power for *reasoning* about our code. Conclusion: reasoning about code {>> 4m 45s → 16:55 <<} -------------------------------- The fallout of all of this is something that our friends over in Lisp land have known for a long time, and it's not the glory of nested layers of parentheses. No, it's that when everything is an expression, you can start thinking about the building blocks of your program in a new way. Loops, conditionals, function calls, and so on are *just like* the expressions were familiar with from other languages. When you look at a program in Python or Java and see the number 2, or a simple strong concatenation, or a mathematical operation, you know how to reason about that. As an expression, you know it has a *value*, and even though the value depends on other things in the program, it's still just a value. In languages where more things are expressions, you can start thinking of *all* of them in that same way. In principle, a function call is no different than addition or subtraction or string concatenation. Neither is any other kind of block. They're just expressions! There are caveats to that, of course: if you write a function which modifies a value you pass into it, or a loop or conditional which modifies items declared outside the loop, you can't think of it simply as that expression value. But, first, note that that's true of statements which include expressions in other languages, too: if you have side effects, you have side effects. That's why it's a bad idea to modify a pointer (say, with a pre- or post-increment operator) *and* do something with its contents on one line in C or C++ code, for example: it makes it harder to understand what's going on, because there are side effects. So all sorts of expressions can have side effects, but wherever you avoid those kinds of side effects, you can think of the terms as straightforward expressions. In Rust, that means that anywhere you're not dealing with data declared as mutable, you can evaluate all blocks as pure, side-effect-less expressions. That in turn makes it far easier to treat all of these things as composable expressions with types and values---whether those expressions are functions or numbers or strings or loops or whatever else. Then we can glue them together in whatever way is most useful and effective, and if we've made careful choices about mutability (by which I basically mean: avoid it in general and make it obvious where you use it), we can see very clearly and explicitly what kinds of transformations we are applying to the data under consideration. All of this, remember, just comes out of the fact that Rust is an expression-oriented language, where nearly all the constructs are expressions which have types and potentially values. It's fantastic! As an aside: I had gotten so used to thinking of functions as expressions whose value is that of *their* final expression that it got me in a little bit of trouble in an interview a while back. I was writing JavaScript for the interview, after a month in which I had been writing a lot of Rust in my free time, and I spent two minutes trying to figure out why a function wasn't behaving as expected; the interviewer finally---and thankfully, he was gentle and sympathetic about it---pointed out that I didn't have a `return` statement. I had become used to thinking of functions as having values, and those values simply being the value of their final expression. It's powerful and useful, and once you get used to it, you miss it when you don't have it. Next time, we'll make a long-promised foray into the challenge that is dealing with lifetimes explicitly in Rust. Outro {>> 1m 20s → 18:15 <<} ----- ### Sponsors Thanks to Hamza Sheikh and Chris Palmer for sponsoring the show this month! You can see a full list of sponsors in the show notes. If *you'd* like to sponsor the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at Venmo, Dwolla, or cash.me. ### Follow/support You can find links to each of those, to other things mentioned on the show, and notes and detailed code samples illustrating macros at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. You can help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend! Thanks to everyone who's added corrections and fixed typos in the show notes; pull requests are great. I also love hearing from you! Definitely say hi on social media, add your thoughts in the thread for the episode on the Rust user forum at users.rust-lang.org, or shoot me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e014-script.md ================================================ # Stringing things along ## Intro {>> 15s → 0:15 <<} Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 14: Stringing things along.* ## News and Follow-Up This week I have some follow-up! First, a few weeks ago I got a couple very helpful questions from listener Jeremy W. Sherman, who pointed out that in my discussion of the "unit" type in episode twelve, I was a bit ambiguous about whether the type has a value. That's because I myself was a bit unclear about the best way to summarize it! As he pointed out: it's a *low-information* type, but it has a value: that's what makes it usable as an expression (because, remember: all expressions have values). That value *is* that it is an empty tuple. Even though that's a little odd to think about, it's useful. In fact, it's *essential* for Rust to have the type safety and memory safety guarantees that it has! My thanks to Jeremy for that clarification! Second, this week I had a really interesting exchange on GitHub with user **Tamir Bahar, @tmr232**, who brought up a point I hadn't fully considered about my discussion of type coercion in C, in episode 11. He pointed out a scenario where adding together a string and an integer doesn't cause a coercion, since it just does pointer arithmetic. It was a close cousin of the example *I* had in mind, where there actually *is* coercion. I'll link to the discussion in the show notes, as I think it's interesting. One of the things that discussion highlighted for me was the fact that the types *are* trivially coerceable in C: depending on what *exactly* you tell the compiler to do, you may or may not get a warning, and you may well get a segfault regardless. Thanks to Tamir Bahar for the thoughtful feedback and conversation! ## Strings in Rust So today we're going to talk about *strings* in Rust. You might be surprised it took us so long to get to something which seems so ordinary, but as you'll see, there's a reason I picked *now* to talk about them. By waiting this long, we've been able to lay the foundation we need to understand pretty much everything going on with strings in Rust, so I have a lot less hand-waving I need to do than I would have if we'd gotten here sooner. One thing to note right away: Rust's strings have some pretty substantial differences from many other strong types you might be used to, especially in C-descended languages. For one, *all* Rust strings are UTF-8–encoded Unicode, not ASCII. For another---and this might be especially surprising to C and C++ developers---they are not null-terminated (so you can have null characters in the middle of strings, and finding a null character is *not* how you find the end of a string). One small benefit of this is that the length of a Rust string is the number you would expect if you hadn't been trained by years of dealing with C-style character arrays. It's the actual number of characters in the string. I think that's excelelnt, but it does require a bit of readjustment. ### Two kinds of strings Another thing which people often find surprising about Rust strings is that Rust has two kinds of strings available to us. They're closely related, and it's easy enough to convert one to the other, but they are different, and the differences are important. The two types of string we see in Rust are the `String` type ("string" with a capital 'S'), and the string *slice* type, spelled `str`. (You'll far more often see it as a borrow, `&str`. I've never seen the non-borrowed form outside the docs, in fact.) The `String` type is an owned, heap-allocated, growable type. Under the hood, it's a vector of UTF-8-encoded Unicode codepoints. The `str` slice type is a reference to a specific chunk of memory, consisting of some specific number of those codepoints. Those slices can be allocated with static lifetimes, or they can point to some or all of a given `String`. As you'd expect, you can create new `String` instances by typing `String::new()`. You can also allocate them with a specific size, with `String::with_capacity()`, which you might do if you know ahead of time how big they're going to be, which can be especially handy if you know a given `String` will only ever have a given value. `String` instances are growable, so if you start out with a default size, or specify the size and it ends up being too small, it's not the end of the world---but there is a slight performance penalty if you have to ask the allocator to give it more memory on the heap. The other *very* common way to create `String` instances is from string slices, including string literals. You can write `String::from("some string literal")`, or you can write `"some string literal".to_string()`---both give you a `String` instance back. Now, a moment ago I said "string slices, including string literals" because in fact a string literal is always just a stack-allocated `&str` slice, with a `'static` lifetime. The same is true of any string literal constant you define in a module. But you can also get string slices---with non-`'static` lifetimes!---from existing `String` instances or as a subset of another `str` slice. Now, I keep saying "string slice"; what do I mean by "slice"? This is just Rust's word for a view into a given sequence of associated memory. As we'll discuss more below, there are *lots* of kinds of slices. You can think of all of them, and thus, for our purposes right now, `&str` slices specifically, as being references to contiguous chunks of memory. Specifically, they're a pointer to that memory, and the length of memory pointed to. ### Unicode Throughout this discussion, I've frequently used the term "codepoints". This is because both `String` and `str` represent Unicode strings. So we need to understand a little about Unicode characters to really see what's goin gon. Unicode strings are streams of bytes which make up *graphemes*. A *grapheme* is what looks like a single character when you're reading. So, for example, when you see the any ordinary English letter, an accented á in Shakespearean poetry, or the ñ character used in Spanish, or the accented vowels in both classical and modern Greek, or the logograms used for Chinese characters, or even an individual musical notation from the relatively recent Standard Music Font Layout, you're looking at a *grapheme*. But those graphemes are often made up of more than one *byte* or *codepoint*. So the Greek diacritical markings take two bytes to represent one character. Many Chinese logograms require three bytes. And Rust strings abstract over this so you can interact with text in whatever language (even musical language) without having to worry about it overall. However, this does mean that you can't index directly into a string like you would a character array in C or a string list in Python. Instead, we can use a specific API provided for this: on any given `String` instance, we can use the `chars()` method to get an `Iterator` over the characters, rather than code points. Then we can use the `nth()` method, which also comes from `Iterator`, to get the character at the visual location we expect. Another consequence of handling strings as Unicode is that the *length* of a `str` slice or a `String` is the number of *bytes* which make up the total set of graphemes in the String. But that won't necessarily be the number of graphemes. If I type the classical Greek word "ἀγαπάω", that will be *eight* bytes but *six* graphemes. ### Dereferencing All the usual rules about mutability, borrowing of references, and lifetimes apply here just like everywhere else. However, when you borrow a `String`, what you get is `&str` reference. That... seems a little strange at first, right? This brings us to the final thing we need to cover in our discussion of `&str` slices vs. `String` instances: dereferencing. When we make a reference to a given type, we can specify, via the `Deref` trait, what it dereferences into. This trait says what happens when you type `*` in front of some name binding, `*foo`, but it also says what happens in this scenario with string types. If you have a type A which defines the deref trait a target type B, and you type `&A`, it will automatically become `&B`. `String` implements `Deref` with `str` as its target, so when you borrow a `String`, you can have a borrowed `str` slice wherever you need it. Here's a concrete example from the standard library. The `str` slice type has a method called `chars()`, which gives you the characters in the slice. But we can also call it on `String` instances! `chars()` expects to take `&str` as its argument. And as you may recall from our discussion of struct methods early on, the `.` syntax for methods is just syntactical sugar for calling a given function with the instance as its first argument. So when you call `.chars()` on some `String` instance, it passes that as the first argument to the method, and since `chars()` expects a `&str` rather than a `String`, it automatically dereferences it for you. Neat! Note two things carefully. 1. This isn't magic. Because it's built on Rust's trait system, it works for any type equally well. You just have to implement `Deref`. 2. It also isn't silent type coercion. The compiler does this for you, but this only happens when you've said explicitly that one type can be transformed into another. If you haven't implemented `Deref` for a given pair of types, *this won't happen*. ### Vectors and Slices Of course, as I've noted, this doesn't just apply to string slices and String instances. But that's true for *lots* of things with Strings and slices: most of what we've said here---basically everything except the Unicode details---is equally applicable to other vector and slice types. These issues tend to come up *most often* with strings, because dealing with strings is such a common case in so many different programming tasks. But a `String` is not a special case in Rust: if you look at how it's implemented in the standard library, you'll see that it's just a struct that wraps a `Vec` vector type. Vectors are a general-purpose, heap-allocated, grow-able memory type in Rust. That's precisely what makes them useful for the `String` type: they're general purpose, so a string can very easily be just one special case with its own additional functionality. But you can just as easily do the same kinds of things with numbers, or enums, or structs, or whatever else. If, for some reason, you need a vector filled with hash-maps which take strings as keys and enums as values... you can do that. The type signature might be a little complicated, but it's not at all a problem as long as the type is well-defined. So for any given vector, you can take a slice of it, and you can pass that slice as an argument to a function, and you can pass back a slice from a function. (Of course, those slices are references, so you have to manage the lifetimes properly in those cases, as we talked about in episode 13.) You can create a new vector from a given slice. You can dereference a vector to get to an underlying slice, as long as the `Deref` trait is implemented. Since `String`s are built on `Vec`, they have access to the whole vector API! Similarly, string slices are, well... slices. In general, the things you can do with `&str` are applicable to *any* slice of any vector, apart from the string-specific APIs like `chars()`. But that's exactly what we'd expect when extending one type with another. (Note that `str` is a *little* bit special, in that it's a primitive type in Rust. But even so, a lot of its implementation is just like you'd see for any other slice.) ### The standard library This is one of the things that I really appreciate about Rust: the way its standard library is built out of the same basic types that we use for our day to day work in the language. There aren't a lot of special cases. If you want to go look at how a String works... you just look at the source and see how it works. And it works pretty much like you'd expect if you already know how vectors work. This has two really helpful effects. First, it means that if a given type in Rust is perplexing you, you can usually figure out what's going on just by looking at its implementation. If you keep digging, you'll eventually see how the pieces fit together---and you usually *don't* have to understand a bunch of compiler internals for that to be true. You just have to be able to understand the basic building blocks of the language. Second, it means there's a lot of pressure on the language team to make sure that those basic building blocks are as good as they can be, because *everything else* is built on them. If vectors were a big mess, strings would be, too. And as a nice bonus, it also means that any improvements to the basic building blocks automatically work for everything built on top of those. Vectors are just structs themselves, with a set of associated traits and trait methods they implement. When you get down to the very bottom of the chain, you'll find some array types and a little bit of actually `unsafe` code that does full-on memory allocation work, as you'd expect, but even that uses ordinary Rust primitives. These aren't really special cases. I'll link to relevant source files from the show notes, because it's actually quite clear how the types are implemented. We shouldn't take this for granted. This isn't the only way to approach language design, and there are plenty of languages out there which *aren't* built this way, but instead rely on special cases in the compiler, special syntax or keywords, and so on to deal with these kinds of things. By building everything on top of these core primitives, and by choosing *really good* primitives to build on, Rust lets us build almost anything. And I mean that. If you have a reason to---say, you're building a real-time operating system in the language---you can rip out the standard library and supply your own. The basic pieces you need are all there. ## Outro So that's an overview of strings in Rust! Next time, we'll start looking at some of the "smart pointer" types and when we would need to use them, and how to use them. As noted in the beginning of the show, I really enjoy feedback. Jeremy's questions and Tamar's comments both made me think harder about Rust, and I learned a lot from both exchanges! ### Sponsors Thanks to Hamza Sheikh, Chris Palmer, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at Venmo, Dwolla, or cash.me, or get in touch with me directly. ### Follow/support You can find links to those as well as to the discussion threads I mentioned at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. You can help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend! So do respond on social media, in the thread for the episode on the Rust user forum at users.rust-lang.org, or via email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e015-script.md ================================================ # Not Dumb Pointers ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 15: Not Dumb Pointers.* ## News and Follow-Up - First, note that in short order after the release of this episode, the tickets for RustConf will go on sale. RustConf is September 10th in Portland. Speakers should be announced fairly soon! - Second, if you're on the *other* coast of the United States, the Rust Belt Rust Conference is October 27th and 28th in Pittsburg, Pennsylvania. The speakers and topics have already been announced, and it looks like a pretty great conference. I'll let you know of more conferences as they come up. You should also keep an eye out for local meetups---or think about starting one! I mentioned in the last episode that I was curious about other podcasts. There *is* one other one out there: Rusty Radio. I knew about Rusty Radio, but I thought they'd gone off the air. I'm happy to find that they haven't, and you can find them on SoundCloud (and of course I'll link them in my show notes). Also, I want to remind you about Exercism. I mentioned it a long time ago but just started playing with it myself: if you're just starting out with Rust, it has a series of problems ranging from "Hello, world!" to "Write a parser for part of the Forth programming language"---with built-in test suites to help you through it. It's *really* good stuff. One other big thing: since the last time I recorded, I actually wrote an RFC! As you may recall, RFCs are the official way changes make it into Rust. In this case, I made an argument for requiring documentation to accompany all new changes to the language. You can check it out at rust-lang.org/rfcs/pull/1636. ## Smart Pointer types Today we're going to talk about a number of kinds of *pointers* in Rust. This will pull together things we've talked about going all the way back to episode 2 and our summary of ownership and borrowing, as well as pieces like the `Box` and `Vec` types. We'll also look at some closely related types like `Rc` and `Arc` and see when and how we might use them, and what some of the constraints on using them might be. This is the kind of episode where there's a lot going on, and it depends heavily on other things in Rust---but it also means we get to see how the pieces *come together* to give us some powerful tools. ### Review: ownership, the stack and the heap, and lifetimes Let's start by briefly reviewing three topics: ownership, the stack vs. heap distinction, and lifetimes. If you start to feel in over your head, don't worry; there's a lot here. It may help to go back and listen to episodes 2, 5, and 13, which covered ownership, the stack and the heap, and lifetimes. First, think back to our discussion of Rust's approach to *owning* data. The basic idea in Rust is that we're going to keep our code safe from things like dangling pointers or bad memory accesses by tracking the *ownership* of every item in the program. One function can *lend* another function a *reference* to a given piece of data, while holding onto the *ownership* itself. Or it can *move* the ownership of that piece of data over to the other function. No piece of data is *destroyed* via a destructor until the function which *owns* it goes out of scope. Once the owning function *does* go out of scope, the data gets cleaned up automatically. Second, Rust (like all low-level languages and many high-level languages) can allocate memory in two places: the *stack* or the *heap*. The stack is where all data which is purely internal to functions normally goes. When you write `let x = 10;` inside a function, it's on the stack. However, sometimes we need data allocated in different ways---for example, because it needs to live beyond the scope of that function, or because we need to be able to resize it arbitrarily (like a `Vec`). For those scenarios, we can allocate things on the *heap*. We've talked about a number of heap-allocated types so far: `Box`, `Vec`, and `String` are all heap-allocated types. In a few minutes, we'll also look at two more: `Rc` and `Arc`. Third, *lifetimes* are Rust's way of making it clear how long a *reference*---when one function *borrows* a piece of data from somewhere else---has to be valid. This becomes very important when talking about these heap-allocated, smart pointer types, because, well... they're all pointers. Now, you *don't* have to write a lifetime on every `Box` reference. But things like `Box` or `Rc` can *contain* references, and when they do those internal references need to use the same lifetime specifies that you would need in any other context where a lifetime would apply, like function signatures or type definitions. ### `Box` Okay, so we've gotten back up to speed on the pieces we need. Let's start by talking again about `Box`, because we'll build on it with a bunch of the other types. Imagine you're writing a program and have an open reference to a file, and you want to be able to read from it any number of places. (Note that I'm not suggesting this particular approach is a great idea; I'm just giving a relatively easy-to-understand example.) You might have a type called `struct FileData`, with some metadata about the file as well as its contents. But if you included its contents, it could end up being a large file, and then you might not want to be passing around the whole type all the time. In that case, it might make sense to create it and return it on the heap, by creating a `Box`. Now you have a *smart pointer* to the connection instance. So why do we call these *smart* pointers? Well, because the pointers we're used to---pointers from C, specifically---are *dumb*. *All* they do is point to things. The semantics of a dumb pointer in C are very, very simple: they point at things. But that means that any and all memory management involving pointers is *of necessity* a job for the developer. The compiler doesn't handle *any* of it for you with heap-allocated objects. Better watch your `malloc` and `free` calls. If you mess them up, you're quite possibly in trouble. Smart pointers, by contrast, have "smarts" to them. When you heap-allocate using `Box`, it has all the same compiler-level cleanup intelligence as any other type in Rust. (And to be clear, other languages have smart pointers, like C++'s `unique_ptr` and `shared_ptr` types. But Rust's have better safety guarantees.) When a smart pointer type goes out of scope in Rust, it automatically gets cleaned up, and so does what it points to. So if you have a `Box` pointing to some data, and it goes out of scope, the pointer itself gets destroyed, and then any cleanup code associated with the type it was pointing to runs for *that* data. Going back to our example where we wrapped our `struct FileData ` in a pointer so we could hand it around. If you've dealt with SQL connections before, you know there's often some cleanup involved: you need to release the connection cleanly so it gets returned to a connection pool, so that other parts of the program or other programs can use it. In Rust, we do this by implementing the `Drop` trait on a given struct and defining a `drop` method which runs when something goes out of scope. (If you're feeling *Rusty* on traits, you can go back and listen to episodes 8 and 9.) So in this case, our `Box` would get rid of the heap-allocated data, but first it would run whatever code was in the struct's `drop` method. The pointer is *smart*. This is the same basic principle that makes types like `Vec` or `String` work: internally, they just employ their own smart pointers (though in those cases, if you get all the way down, it's the still-unstable `Unique` type, not `Box`). ### Reference-counting So that's a nice combination of increased convenience and safety over C-style dumb pointers on its own. But where this gets really good is when dealing with, say, types that need to cross threads. If you have some data you need to pass from one thread to another, and you know that the data is immutable, you're fine: you can just "move" the data to the other thread. And in many cases in Rust, that's actually exactly what you'd do. Passing things around behind smart pointers all the time is actually an anti-pattern: this isn't Python or C#, and we don't have a garbage collector cleaning up heap-allocated memory all the time. But there *are* times you need smart pointers, and times when you need more than even a `Box` gives you. For example, if you needed to *share* the data between two threads---that `FileData ` instance we talked about before, maybe---how would you know when it was safe to get rid of it? If it went out of scope in one thread, and the `drop` ran, but another thread was still pointing to it, you'd be in the same familiar mess everyone who's tried to write thread-safe code in C has found themselves in. And in that case, it wouldn't matter whether the data was mutable or immutable. Like I said: a mess. And of course, if you think about it, if you start sharing around references to objects, you can run into that same problem even just within one thread if you have *any* asynchrony at all. But gladly, smart people have come up with some other *smart* pointer types that can help us with this problem. For thread-local, immutable data, we have the `Rc`, or *reference-counted* type. This lets us have more than one reference to the same data when we need it. The `Rc` type does just what the name says: it *counts* the number of references to a given item. You can't mutate the item, but you can pass around references to it as much as you like within a single thread. Whenever you need another reference to it, you get it by calling the `clone()` method on the `Rc`. So, back to our example of a `FileData`, if we had an instance named `ffd`, we'd wrap it in a reference counting pointer by writing `let wrapped_data = Rc::new(fd);`. Then when we wanted to get a copy of the pointer to let other pieces of the program use it, we'd write `wrapped_date.clone()`. Under the covers, the `Rc` has a count of *strong* pointers to the data it wraps. Any time any pointer reference is created, the count goes up. Any time one of those pointers goes out of scope, the count goes back down. As long as there is at least one *strong* pointer, the underlying data *cannot* be deallocated. In addition to strong pointers, there can also be any number of *weak* pointers. Weak pointers don't contribute to the count. They're a way of expressing, in the type system, that the thing they point to doesn't *have* to exist. You can think of them like `Option`, but for reference counts---and in fact, when you try to access them, an `Option` is exactly what you get back. So how would you *make* a weak pointer? Normally, by "downgrading" an existing `Rc` instance. In our ongoing example, where `wrapped_data` was the `Rc` we made a minute ago, you might write `let weak_fd_ref = Rc::downgrade(wrapped_data)`. Then to get back at the data, you can call `weak_fd_ref.upgrade()`, which will give you the `Option` I promised a minute ago. If you're wondering when exactly you'd need this, well, suffice it to say there are a lot of circumstances they'd apply in, and we'll come back to that at some point in the future. For today it's just enough to know they exist, and how to make one. Now, everything we just talked about is grand and all... but `Rc` instances are only allowed within a single thread. But of course there are times we need to share data *between* threads. For that very purpose, we also have the `Arc`, or *atomically reference-counted*, type. *Atomic* types in general are types that (and here I'm quoting the Rust API reference), "when used correctly, synchronize updates between threads." That means that when we use them correctly, they're a *safe* way to share data between threads. Like `Rc`, `Arc` lets you pass around *references* instead of *copies*, while maintaining safety guarantees. The API is basically the same, too: you make them with `Arc::new()`, downgrade them with `Arc::downgrade()` and upgrade their corresponding `Weak` types with `upgrade()`. What's different is that, because you need stronger guarantees about behavior, there is additional machinery for making sure that the operations are *atomic* so the threads stay in sync. With both `Rc` and `Arc`, you can use the `make_mut()` method to *always* get a mutable reference to the data as long as the wrapper is mutable---even if there are outstanding references. How? By *copying* the data if necessary, an approach called *copy-on-write*, where you don't make copies of data unless you're *changing it*. If you don't need to change it, you can use their `get_mut()` methods instead---they just return `Option`, so if there are other outstanding references, you'll get back `None`, because you're not allowed to mutate it in that case. ## Outro This behavior, and in fact everything we've just talked through, is a result of two of Rust's core philosophies: *zero-cost abstractions* and *only pay for what you use*. It's not that doing something like reference counting is *free*; it's that you have to pay that cost no matter what if you're doing atomic operations, and Rust doesn't make you pay any *extra* cost beyond what you would write by hand to get the same safety and performance. Anyway, hopefully you have a better idea of how the smart pointer types work in Rust now, and hopefully you'll feel more comfortable using them when you need to (and understanding what's going on when you see them in other people's code). I know my own understanding got a lot clearer as I prepared! ### Sponsors Today in particular, I'd like to highlight the kind people sponsoring the show. If you noticed an increase in the quality of the audio today, it's because of the generosity of the listeners who've steadily contributed to the show over the past many months. I was able to buy a top-notch recording setup through that funding, and it's now paying off for all of you listeners as my audio quality should be much improved from here on out. So: thanks *very* much to Chris Palmer, Daniel Collin, Raph Levien, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at Venmo, Dwolla, Flattr, PayPal.me, or cash.me, or get in touch with me directly. ### Follow/support You can find links to those as well as some examples of using smart pointers at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. You can help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend! So do respond on social media, in the thread for the episode on the Rust user forum at users.rust-lang.org, or via email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e016-script.md ================================================ # `RefCell`s and code smells ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 16: `RefCell`s and code smells.* ## News and Follow-Up - The first community survey came out on June 30 (after I recorded with Raph Levien, but before I released the second half of the interview). I'll link the blog post in the show notes---there's a lot of really interesting stuff in there. - Rust 1.10 came out on July 7. The big highlight features from it were: + stable support for defining what should happen when a `panic!` occurs in your code: do you unwind nicely, or just abort immediately? Previously, Rust always unwound nicely; now you can tell it to abort instead---a nice improvement for people writing things like operating systems, but also, depending on what you're doing, it might just be nice overall, as it gives you roughly 10% faster compilation and roughly 10% smaller binaries. + the compiler got less memory hungry *and* faster. Hooray! + the compiler now knows how to generate a new kind of dynamic library---one much better suited for embedding Rust in other contexts, like using it as a library for some piece of functionality in another application. + this was the first release of Rust which is able to be built using *stable* Rust---you no longer have to use a nightly version of the language to build the language itself. So Rust 1.10 was built with Rust 1.9, and the upcoming Rust 1.11 will be built with Rust 1.10, and so on. - rustup 0.3.0 came out July 14th. It fixed a bunch of bugs, improved the user interface in some small ways, and laid the foundation for using `rustls`, a TLS library written in Rust (and therefore hopefully safer and more reliable than the existing, C-based TLS implementations out there)! - the JetBrains Rust IDE, currently just called IntelliJ Rust, got a website: intellij-rust.github.io. Check it out! More importantly, if you use any JetBrains IDE, you can and should install the plugin and play with it---it's coming along *very* nicely. - Carol Nichols and Jake Goulding launched Integer32, a Rust-focused consultancy. To my knowledge (which is admittedly *very* incomplete!), it's the first of its kind. I suspect it won't be the last, since the number of tech companies publicly discussing their Rust usage is going up all the time. - Finally, there's a really interesting-looking talk on a tool called Tango that lets you do "literate programming" in Rust---i.e. you write in Markdown and then insert GitHub-style code snippets of Rust, and it's compilable as actual Rust. I'll probably be doing some of this going forward! I'll link both the talk and the source. ## `Cell` and `RefCell` In the last normal episode, we talked about smart pointers---the more ordinary ones like `Box` or `Vec`, and the reference counting ones like `Rc` and `Arc`. We also briefly mentioned when you'd want to use those, and then in a happy turn of events, those same topics came up quite a bit in my interview with Raph Levien. I was already planning to come back to this topic, but the interview made it even more appropriate, and I had several listeners request it explicitly, so today we're going to talk about *using* the smart pointer types, with a bit more detail than we covered last time. Specifically, we're going to talk about two things: 1. dealing with the `Cell` and `RefCell` types with immutable containers which have mutable contents 2. using the `Borrow` and `AsRef` traits to make it easier to deal with related data types in API design One thing to keep in mind: although it's important to know how these things work, it adds a *lot* of complexity. If you can simply avoid having to deal with smart pointers in a given instance, and let the Rust compiler just help you out with normal ownership and borrowing semantics, *do that instead*. You will be glad you did. There are definitely times when you need to opt into the more complex things you can do with these smart pointer types, but don't default to them. Treat them like a "code smell"---the idea of something that isn't necessarily *bad* in and of itself, but which can be a signal that something is wrong if you see too much of it. If you smell a *little* bit of fish, it's fine (and it might even be good). If you smell a *lot* of fish, it's nasty. The same thing goes for "code smells": using a `Box` here or an `Arc` there is fine, and even *good* sometimes. But if they're everywhere, there's probably a better, more Rustic way to approach the problem---one that will perform better, give you easier errors to diagnose at compile time instead of run time, and hopefully be easier to write and maintain, as a result. ### Exterior Immutability and Interior Mutability (`Cell` and `RefCell`) Now, into the meat of the episode. We talked in e015 about how you can use `Rc` and `Arc` to handle shared data within a thread and between threads respectively. We talked about how to deal with the case that you need to get at the data within them using the `get_mut` method if there is only one strong reference and no weak references to the data. All of that was well and good, but it left us with a real problem---one which might not have been especially apparent to you, but which will become increasingly annoying if you spend any significant amount of time working with the `Rc` or `Arc` types: *what if you need the data to---at least potentially---be mutable from multiple places at runtime*? Let's say you're building some data structure which multiple threads need to be able to access, and where you can't know at compile time whether the reference count will be zero. Say, further, that you've declared the wrapping smart pointer as immutable, because you want to make sure that no one is changing it willy-nilly. How would you do that? And in fact, this issue can come up with smart pointer types in general. Imagine you had a `Vec` wrapping some other `struct` type you'd defined---and you wanted the `Vec` to be immutable, so that different clients could read the contents of the `Vec` but not modify it, but you *also* wanted the `struct` instances *within* the `Vec` to be mutable. We literally cannot do that by default: if the `Vec` instance is immutable, so is everything it contains. (You can take a look at the show notes for the episode to see this in practice. There's a commented-out line there which simply won't compile if you uncomment it, for precisely this reason.) So whether we're dealing with simple vectors of data, or sharing data between threads, there are times when we might want an *immutable container* containing *mutable data*. This is where `Cell` and `RefCell` come in. We could wrap that custom struct inside a `Cell` or `RefCell`, and then if we wanted to, say, iterate over the items of the `Vector` and updating the contents of each `struct` we had defined within it, we could do that. With either `Cell` or `RefCell`, we would just wrap each item in the corresponding `new()` function when adding it to the vector. So if we had a vector named `my_list_of_things`, and a struct named `Thing` with a bog-standard `new()` method (clever, I know), we would type `my_list_of_things.push(Cell::new(Thing::new()))` when we added it to the vector. The *type* of the vector would then be `Vec>`. That is, it's a *vector* wrapping a *cell* wrapping a *thing*. As you can see, we've dialed up the complexity a fair bit in order to be able to get this flexibility at runtime. The difference between `Cell` and `RefCell` is whether we're dealing with data that can be copied simply or not. More specifically, we can use the `Cell` type to wrap up any type which implements the `Copy` trait, which defines how to do a straightforward copy of the underlying data. One easy way to think of it is: anything you could trivially `memcpy` in C, you can implement `Copy` for in Rust. In general, value types can always implement `Copy`, but reference types may not be able to---`String`, for example, doesn't, because it uses `Vec`, and `Vec` doesn't implement `Copy` (and I don't think it *can*, because its size can change dynamically). This also means that using `Cell` doesn't have any cost at run-time: it's not doing anything special, because it only wraps stack-allocated, value data, so it gives you a way to say, "Hey, these things here can be mutated freely" and the compiler can know that it's still safe. You might write a bug around this if you incorrectly assumed the data was immutable, but it would be a *logic* issue, not a *memory safety* issue. So how do you *use* a `Cell`? Well, after you've wrapped something up in it, you can just use the `get()` and `set()` methods to read or write the value respectively. So in our `Vec>` example, if `Thing` were just a type alias for an integer, we could double it by doing a for loop over the vector. Each step through the iterator would give us a `Cell`; we would then use the `get()` method to get the old value and the `set()` method to set the new value, and when we're done, we'll have updated the value inside each `Thing` in the `Vec`, all while only having a standard, immutable reference to the `Vec` itself. And we won't have incurred any runtime costs; we'll just have let the compiler know, by using the `Cell`, that it is safe to mutate these particular fields even though you can't satisfy the borrow checker directly. Neat! Now, by contrast with the `Cell` type, `RefCell` *does* have a run-time cost, because it does *run-time checking* that what you're doing is safe. The Rust book describes it as being like a single-threaded mutex---that is, a data structure which requires you to *lock* it before you write to it, as a way of signaling to anyone else trying to read from or write to it that it isn't safe, and then *unlock* it when you're done so that others can access it again. In other words, it's kind of like it's doing borrow checking *at runtime*, for situations where you can't do it at compile time. Any type which can't implement `Copy` but needs the interior mutability we discussed is a candidate for this, but you have to think carefully about that tradeoff. The other big downside is that because we defer some of the error checking to runtime, you can end up with a `panic!` instead of a compile error. When you need it, you need it, though, and the upside is that you're still getting good guarantees about the behavior---far better to get a `panic!` and a graceful shutdown of the program with a nice stack trace than to have it explode somewhere apparently unrelated because you mismanaged the memory. Not, of course, that I've had that happen to me on a regular basis in legacy C and C++ code I came on to maintain. Using `RefCell` is fairly similar to using a `Cell`, but instead of using the `get()` or `set()` functions, we use the `borrow()` and `borrow_mut()` functions. If we just need to *read* the data, we'll call `borrow()`, and if we need to *write* the data, we'll call `borrow_mut()`. As those names make clear, we really are doing borrow-checking at run-time! If we `borrow()` somewhere in our code, we can `borrow()` other places as well: just as with compile-time borrow checking, it's perfectly safe for lots of different parts of our code to *read* memory at the same time. However, if any part of our code has run `borrow_mut()`, it is *not* allowed for other parts of our code to try to use either `borrow()` or `borrow_mut()`, for the same reason you're only allowed to have one mutable reference and zero other references in normal, compile time borrow checking in Rust. If you *do* try to call `borrow()` or `borrow_mut()` on some piece of data which already had a mutable borrow out, you'll get a `panic!`. One upshot of all of this is that if you have a type wrapped in `Cell` or `RefCell`, you only need *a reference* to some data---not a *mutable reference to it*, not a *unique* reference to it, like we usually would---to satisfy the borrow checker. So how *do* you know when to use `Cell` or `RefCell`? Well, again: default to *not* using them. If you can just use normal references and borrowing and let the compiler strictly check all of it at runtime, do that. Then, if you *can't*, or if it becomes especially difficult, evaluate these two options. Do you reuse a given piece of data all over the place (so keeping track of borrows is hard, even impossible), but you only mutate it relatively rarely? It might be a good candidate for wrapping it up in a `Cell` or `RefCell`. If it implements `Copy`, stick to `Cell`. As part of that, if you have a large data structure you're dealing with, see if you can just wrap *part* of a type with `Cell` rather than the whole thing, so you don't incur the cost of copying a large struct around. If you have a type that can't implement `Copy`, and so can't just replace the data "for free" at runtime, then look at `RefCell`. You'll still get good guarantees about how it behaves, the performance penalty is pretty small, and if or when something *does* go wrong, you'll usually have a pretty good idea where and why from the `panic!` message. ## Outro -- Sponsors & Following Next time, we'll follow up with a discussion of the `Borrow` and `AsRef` traits, and then put together `Borrow` and the `Copy` trait we touched on today to talk about the `Cow` type. Hint: it's not a large mammal! On a personal note---thanks to everyone who has listened to the show. Between new episodes and the back catalog, New Rustacean had over 11,000 downloads in June, and has already had over 8,000 by mid-July. When episode 0 came out back in September, I had 76 downloads the whole month. That jump amazes me, and inspires me to keep at it---the Rust community is pretty fantastic. So thank you all for listening! Another thing which inspires me in the sponsors, whose generosity is a huge part of making it possible for me to keep making the show. So thanks, as always, to Chris Palmer, Daniel Collin, Raph Levien, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes, and the top tier of sponsors on a dedicated page on the website as well. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at a variety of other services listed at newrustacean.com. There you will also find links to the news items from the top of the show, and some examples of using smart pointers *ergonomically* as we discussed today. You can also follow the show on Twitter \@newrustacean, or follow me there \@chriskrycho. You can help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend! So do respond on social media, in the threads for the episode on the Rust user forum or on Reddit, or via email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e017-script.md ================================================ # Point me where I need to go ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 17: Point me where I need to go.* ## News and follow-up - Raph Levien posted an interesting post on Medium looking at the font renderer he mentioned briefly in my interview with him. It's crazy fast, and the post is pretty interesting. - Aaron Turon, one of the Rust core team members, wrote up a proposal for a "Rust Platform" to help make it easier for new Rustaceans to get up and going---trying to get some of the benefits of the "batteries included" standard library of something like Python, while still keeping the lean, light *actual* standard library. There's been a lot of interesting discussion about that, so I'll link it in the show notes! - Nightly Cargo builds now support the ability to "vendor" dependencies, that is, specify a source for them besides their source repository---which is helpful for e.g. builds in environments where going out and hitting GitHub isn't possible, or where the dependencies all need to be verified ahead of time. - Nightly Rust now has MIR turned on by default! It was previously available, but only behind a feature flag. We're quickly headed toward a lot of compiler improvements, as it looks like it should land sometime in the next few major releases. (For more details on what MIR is, you can go back and listen to news episode 1!) ## Referencing and Dereferencing One listener, \@gazhaze on Twitter, asked if I'd covered the dereference operator or the general behavior of dereferencing, and I realized I hadn't. In all the code samples I've given, I've basically assumed the syntax there, but it's worth slowing down and thinking about what we mean when we use a given piece of syntax, and how that fits into the language's model for safety. It's also important for understanding a lot of performance considerations! And given that the original plan was to spend this episode talking about some traits and types which make heavy use of the semantics around referencing and dereferencing things in Rust---but to do *that*, we need to talk about what we mean by "references" and "values" and "pointers" and "dereferencing" in the first place. Most modern languages (from C to F^♯^) have some idea of dealing with data either by *value* or by *reference*. And sometimes it *matters*. I once ran into a problem in a piece of Python I'd written where something was going wrong precisely because a given bit of data was being passed around by reference, not by value, and until I realized that, I couldn't solve the problem---even though Python does all of that "behind the scenes," so to speak. As such, I hope this helps you specifically with Rust, but understanding these ideas should help you whatever language you're writing in. ### References and pointers So when we talk about references and pointers, what *exactly* are we talking about? If you're coming to Rust from a language like Python or Ruby or JavaScript, and you don't have a background with lower-level languages, you've probably heard the words batted around, and you may even have gotten to the point where you know how to use the relevant operators (which we'll discuss further in a minute). But if you're still wondering what they are, or if you just need a refresher, hopefully this will help. When you're dealing with any piece of data in a program you're writing, it has a particular location in memory. That location is just an *address*, usually written in hexadecimal, but ultimately just a number, that ultimately maps down to a specific location in the RAM where the computer is currently storing that data. That's true whether you're talking about something as simple as an integer or something as complex as a vector of structs with refcells pointing to strings in them. *Everything* has an address. (One thing to note as we go: the program doesn't actually have a *direct* address to the RAM, but rather an address relative to its own block of memory as allocated by the operating system. The operating system maps that address back to the RAM itself; that's an important distinction for security purposes.) When you call a function with some data, there are two ways you could give it that data. Since every function gets its own memory on the *stack*, we could just allocate the required amount of memory in the stack and just copy the data into that new space. Then we could just pass the data directly to the function and be done. This is simple and straightforward, and it's also *always* perfectly safe, because the original memory location is untouched. The new function can't accidentally smash it. (We'll come back to that concept a *lot* more in the next episode.) But there are downsides to doing it that way. Copying all the data for every argument every time we call a function will get expensive. What's more, if we wanted to *change* the value in the original, we'd need to copy it back (by returning it) when we were done, and then overwrite the original memory with the new value. That's a *lot* of work. We can run into performance problems pretty quickly. So, remembering that every item has an address in memory, we can do something which is a lot faster *and* which uses a lot less memory: we can just hand around that address instead. When we do that, we're handing around a *reference* to the data. If we know the address and the kind of thing we're talking about---a struct, or an enum, or whatever else---then we know how big it is, and we know how it's shaped, and we don't actually have to copy the data to be able to use it. We do have some concerns about safety doing that, though. If we have two functions running in parallel, and they both have the address of a given data structure, what happens if they try to write to it at the same time? Or even, what if one of them tries to read from it while the other one is writing to it? Or what if you just make a mistake and write the wrong size object to a given address---one that's too big for the space, and so goes past the end of it and crashes into some *other* object's memory? Because, remember: at the end of the day our data is all just values stored at specific addresses in memory. So you can easily end up with bad data, and have no way of knowing. We'll come back to those safety issues in just a moment. First, though, let's talk about what we mean by "pointers" now that we have a good idea what references are. A pointer, strictly speaking, is the content of a *variable* whose type is a *reference*. Instead of the content of the type being an integer or string or whatever else, the content is the *address* of an integer or string or whatever else. So, when you pass an argument *by reference* to a function in Rust, the type of the argument is a *reference* and its content is a *pointer*, a number pointing to a specific address in memory. However, the vast majority of the time (and *all* of the time in safe Rust), you don't have to think about the value of that address---just the kind of thing it's pointing to, and the fact that you have a reference instead of a value. When you perform operations with a reference, the value of the memory address (that is, the pointer value) is both irrelevant to you and, in general, inaccessible to you. This is very different from C or C++, and it's precisely where Rust's idea of *borrowing* and *ownership* comes from. Rust keeps us from making the kinds of mistakes we talked about above in a couple ways. The first, and most interesting, is by making sure there is only one mutable reference to data at a time. What that *really* means, in light of everything we've just said, is that Rust makes a strict compile-time guarantee that only one scope is allowed to have *write* access to given memory address at any given time. But an unlimited number of scopes can have simultaneous *read* access to an address as long as nothing has *write* access to it: we know the data at that address won't change. When we talk about *lending* or *borrowing* a reference, then, we're really talking about handing around pointers to data, with strict rules about whether the scope getting a reference is allowed to write to that address or not. As for smashing the memory by writing the wrong kind of data to a given address, this is where Rust's type system and its rules about unsafe code come in. C and C++ won't let you write the wrong kind of object to a given location... unless you just coerce it to the "correct" type, or cast it to arbitrary memory `void *`, both of which are bad practice but totally allowed by the compiler. Both of those are actually impossible in safe Rust, which requires you to define safe, explicit transformations from one type to another---and, just as importantly, Rust doesn't actually expose the *pointer value* in the reference. Instead, it just lets you read and write to the data behind the reference by *dereferencing* it---but without ever needing to know the memory address yourself. (You can get the memory address, and manipulate it directly, in unsafe Rust, and there are times you do need to do that---but it's not *most* of the time, even for high-performance code, because the primitives Rust supplies for things like iteration, for example, are both safe and very performant.) One other important thing to understand: I've been using a simplified version of how pass-by-value works, to keep it easier to understand. In reality, modern compilers (for a variety of languages) are generally smart enough *not* to actively I copy the memory every time you pass by value if it isn't necessary. Thus, when you "move" an object's ownership, we actually *don't* have to copy the memory every time. If the LLVM internals of the Rust compiler can see instead that the data ownership has changed in ways it understands, it can often build out the final program so that those bits of data *aren't* copied. There's a lot more we could say there, but for now I just wanted to make clear that moving data from one owner to another in Rust isn't always as costly as it might seem if you think it's always doing full copies. (As is usually the case, when you're optimizing, you should *check* for what uses large amounts of memory or takes a lot of time, rather than assuming!) ## Using References Now that we have a decent idea what's going on with references and pointers, let's look at the syntax for using them in Rust. There are 3 basic operations we're interested in: - declaring that a type is a reference - making a reference from a given piece of data - getting at the data behind a reference The first two of these operations use the *reference* operator, and the last one uses the *dereference* operator. We'll tackle them in that order. ### The reference operator (`&`) First: we denote a reference with the ampersand character. When we declare a reference, we use the `&` in front of the name of the type it's referencing. So when you have a type like `DataStore` and you see `&DataStore`, you can read that *type signature* as "a reference to a `DataStore`". Likewise, you read `&mut DataStore` as "a mutable reference to a `DataStore`". Second, we specify to pass a given value *as* a reference by using the `&` operator on the name of the given piece of data. So if we had written `let some_store = DataStore::new()`, we might think about a function `use_data_store()` which takes a reference to a `DataStore`, defined just like we said above. To pass a reference, we would write `read_from_data_store(&some_store)`. You can read that as "call `read_from_data_store()` with a reference to `some_store`". If we were passing a mutable reference, for example if we had an `update_data_store()` function, we would call it like `update_data_store(&mut some_store)`. You would read that like "call `update_data_store()` with a mutable reference to `some_store`". And of course, remember that you can only pass mutable references to mutable data! ### The dereference operator (`*`) Now, once we *have* a reference to some data, because the content of that reference is the pointer, rather than the data itself, we need a way to get back to the data. That way is the *dereference* operator, which is called "dereference" because it takes a reference type and, well.. *de*-referencifies it, if you'll allow me to make up a silly word. We denote the *dereference* operation with the star character. Writing `*` in front of some piece of data gives you access to the original data, and then we have something with type of the original kind of thing being referenced. Let's go back to our example with the `DataStore` type, and imagine that it was a struct with a field called `contents`. So in our example with a data store, inside `read_data_store()` we might do something like check a value `some_data` by writing `if some_value == *some_store.contents`. If we tried to do this comparison *without* the `*` operator, it would fail to compile and we would see a type error, because we would be trying to act on the *reference* to this `DataStore`, and the reference (whose content is just a pointer) doesn't actually *have* a `contents` field. But when we dereference it, we get back the actual `DataStore` type, which does have a `contents` field, and then we can make the comparison. For a somewhat more complicated example of using both with an enum and pattern matching, see the show notes. ## Outro -- Sponsors and Following And that's it! Once we understand the concepts behind them, the reference and dereference operators themselves are pretty simple. And that gives us the *background* we'll need to tackle the `Borrow` and `AsRef` traits, which will let us generalize these ideas to our smart pointer types---and that in turn will let us look at the `Cow` smart pointer type. Thanks as always to the sponsors who help make the show possible! This month, the sponsors included Chris Palmer, Daniel Collin, Eric Fulmer, Jared Smith, Raph Levien, Stephen Murawski, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes, and the top tier of sponsors on a dedicated page on the website as well. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at a variety of other services listed at the show website: newrustacean.com. There you will also find links to the news items from the top of the show, and code samples illustrating referencing and dereferencing data. You can also follow the show on Twitter \@newrustacean, or follow me there \@chriskrycho. If you enjoyed the show, please help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, sharing it online, or just telling a friend! Also, please do respond on social media, in the threads for the episode on the Rust user forum or on Reddit, or via email at hello@newrustacean.com. I love hearing from you! Until next time, happy coding! ================================================ FILE: docs/e018-script.md ================================================ # `Borrow`, `AsRef`, `Deref`: my head hurts now ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 18: `Borrow`, `AsRef`, `Deref`: my head hurts now.* ## The `Borrow` and `AsRef` traits ### Set the Stage Back in episode 17 (a long time ago for those following along with the show in real time!), we talked about references in Rust, and looked at the referencing and dereferencing operations. And we've also talked about a variety of data structures and heap-allocated objects like the `Box` and `Vec` and `String` types. In this episode, we put a bunch of those pieces together. We're going to talk about the `Borrow`, `AsRef`, and `Deref` traits. If you listened to my interview with Raph Levien, you'll recall that we mentioned (and neither of us could remember initially which was which!) the first two of those traits. All three are really important for designing easy to-use APIs, *especially* when you're working with those heap-allocated pointers. Borrowing and taking things by reference seem like pretty fundamental building blocks in Rust, right? And indeed they are. The ampersand borrow/reference operator isn't overloadable. But how it works is something you can define and customize for each type you create: using the `Borrow` and `AsRef` traits. Now, if you're like me, you have two questions: 1. Why would I *need* to customize this? 2. Why are there three different traits for borrowing and references? That latter question is precisely why---in a section which would have been ridiculous to put on air---Raph and I had to stop in the middle of the interview and go look up the difference between `Borrow` and `AsRef`. For that matter, it's the reason there's a note about it in the standard library docs and a dedicated section in the Rust book about it! But we'll come back to that in a minute. And that's not even mentioning `Deref`! In order to get to those questions, we need to have a handle on what each one of these types actually *does*. ### `Borrow` Say you have a basic struct type, and that it's allocated on the stack as usual. You get your normal borrowing and move semantics when you're dealing with the type, as we've discussed before. So if you *borrow a reference* to it with the `&` operator, you have a *pointer* to the type, and depending on whether the original instance was mutable and whether you passed a mutable reference, you may be able to change the object where you borrowed that reference. All well and good. But---and here, let's thing about this with the `String` and `str` types in mind---what if you wanted to build something like a `HashMap`? Remember that `String` is a `Vec` of `u8` data validated to be valid UTF-8, and `str` is a slice of `u8` data validated to be valid UTF-8. Presumably you would want those two things to hash to the same thing---they're both just UTF-8 strings!---and so far as possible you wouldn't want the consumers of your `HashMap`'s API to have to think about what they were handing in. So the `Borrow` trait lets us abstract over this. We can `impl Borrow` for a type by implementing a `borrow` method on the type. Then anywhere we need something which can be borrowed as a UTF-8 slice, we can explicitly call the `borrow` method, and any type which implements it can be used. This is just mashing together this specific trait with generics, but it becomes really helpful when you're implementing something like a `HashMap`. And indeed, the `HashMap` in Rust's standard library does *exactly* this: its `search`, `get`, `contains_key`, and `remove` methods (and the mutable variants where applicable) all explicitly require one of their arguments to have a type the main key of the `HashMap` can be borrowed as. So if the `HashMap` has a `String` key, and you pass it a `str` argument, that's fine: it can call `borrow()` on the `String` instance and get a `str`. We could do the same thing with our own custom types, too. Say you had a function which you needed to be able to borrow as a slice of unsigned-eight-bit integers. You would write the function as `fn takes_a_borrowable>(slice: B) { ... }`. In the body of the function, wherever you actually needed at the borrowed contents, you would just type `slice.borrow()` and do what you needed with it. Then you could pass in an actual slice of `u8`, or you could pass in a `Vec`, or a `Box`, `Rc`, or `Arc` around a `u8` slice, or your own custom type. As for your own custom type, say you had a chunk of data which made sense to represent as a slice of `u8` values, and some associated metadata you were going to carry along with it. (I have no idea what this would be that isn't a unicode string off the top of my head; just roll with me here.) When comparing this to other things, though, the metadata is irrelevant and the `u8` slice is all that matters. You would just implement `Borrow` for the `struct`, where the `borrow()` method returned a reference to the slice contents. So that's how `Borrow` works, and the example I gave at the outset is the main time you'd want to use it. `HashMap`s and things like that---types where there is some kind of underlying equivalence you need to be able to get at---are prime places to use `Borrow`. And note that the *equivalence* relationship is such that you don't care whether you own the data or not: you're just *comparing* it. As such, you're always fine *borrowing* it. If we wanted it to dereference into a different type, we'd need to implement the `Deref` *trait* instead. More on that one in a moment. ### `AsRef` First, though, let's talk about the other trait discussed in my interview with Raph Levien: `AsRef`. More explicitly, we're talking about `std::conversions::AsRef`: and the module namespace tells us something about the semanatics of this trait. It's a way of converting one kind of reference to another kind of reference. Remember that: it's important and we'll come back to it in just a minute. First, though, let's talk through the signature. Just as `Borrow` only has the `borrow()` method, `AsRef` just has `as_ref()`. And the signatures are nearly identical. Both of them are generic over a type with a compile-time-known-size, and the signatures of both functions are the same: they borrow `self` and return a reference to the type over which they're generic. Above, we talked about using `Borrow` for using related keys for `HashMap`. What about `AsRef`? We use it for things like converting between operating system string types, or from a `str` to a `u8` slice. Think of it this way: every pointer to a `str` can be a pointer to a `u8` slice, because all `str` instances are composed of `u8` data---they just have *more* guarantees than a plain `u8` slice does. Those guarantees mean you can't implement `as_ref` from `u8` to `str`, but you can readily implement `as_ref` from `String` to `u8`, too. Note that in each of these cases, we *do* care that we are getting a reference to something. The whole point here is to have something we *know* is a reference, and then to do something with that reference---unlike `Borrow`, where the point is that we want to treat both owned and borrowed data identically. ### `Borrow` and `AsRef` As we noted from the outset: `Borrow` and `AsRef` are pretty similar. The difference in their signatures... is the name of the trait method. This close relationship shouldn't be a surprise if you've followed along with the show, or if you're familiar with Rust's core ideas more generally. *Borrowing* is Rust's way of reasoning about ownership when we make *references* to a given piece of data. So what separates `AsRef` from `Borrow`? Basically, it comes down to what you're actually using the conversion for. If it's for doing some kind of comparison for two types, you'll generally want `Borrow`. If it's for *converting* one type to another, use `AsRef`. You can see where the name for `AsRef` comes from: you can think of it as being a trait for *converting* a reference to one type *as a reference*---`AsRef`---to another type. `Borrow` is a little hazier. Yes, we're *borrowing* a reference from one type to another, but, well... that's kind of what `AsRef` is too. I'll freely admit: `Borrow` isn't a particularly descriptive name in terms of distinguishing it from `AsRef`. But in the Rust standard library's defense, it's hard to come up with a better name here: `AsRefButWithInterchangableEquivalenceOrOrderingToo` doesn't exactly roll off the tongue. So `Borrow` it is. Just remember: use `AsRef` for cheap conversions between types which are identical under the covers. Use `Borrow` for getting at relationships of *equality* or *ordering*. Use `AsRef` when you *need a reference*. Use `Borrow` when you don't care what the ownership state is. ### `Deref` Note we're *not* here changing the behavior of the dereferencing `*` operator with either `Borrow` or `AsRef`. You can see this if you implement either `Borrow` trait for a simple struct which wraps an integer, and try to pass a reference to that struct to a function which takes a reference to an integer. It won't work; the compiler will complain that you passed it a reference to the wrapper, not a reference to an integer. If you're already fairly familiar with Rust, you either already know where I'm going, *or* you're wondering how something like passing a reference to a `String` can work in functions which take a reference to a `str` as an argument. For this, we need the `Deref` trait. This is one of the only places in Rust where an implicit conversion between types can happen. And I say implicit because it's implicit from the point of view of the *caller*, but it's still explicit in the sense that you have to define *exactly* how a dereference operation is going to behave. It's still explicit *somewhere*. But if you have a good reason to---the `String` and `str` example is one such *very* good reason, in terms of the "ergonomics" of using the language. If you had to write `some_string.as_str()` every single time you needed to get a string reference from a `String`, it would get old in a hurry. The same is true for `Vec` and slice types. We have a nice out: `std::ops::Deref`, combined with the language feature called *`Deref` coercion*. As its module name indicates, this is an *operator* overload, unlike `Borrow` and `AsRef`. When you use the `*` operator, it uses the `Deref` trait to define how to dereference the data in question. In many cases, that'll be incredibly simple. In others---say, smart pointer types---there may be a layer of indirection to remove. You might have a wrapper type which you're just using to provide extra data *around* some underlying value, but where you want to be able to get at the contents of without doing something like `*MyStruct.its_internal_contents`; it would be nice to just write `*MyStruct` instead. The real power here comes when we combine the trait with the the `Deref` coercion rule. This rule says that where you have a dereference defined from some type T to some other type U, anywhere which takes a reference to T can automatically be coerced to act like references to T. So, going back to our little type which just wrapped around an array slice: if we implemented `Deref` for that slice type, any place which takes a reference to a slice can also take a reference to our type. This isn't dangerous (though it can be surprising the first time you see it), because we've defined exactly what the coercion relationship is---and all in `safe` Rust code. If you define a way to dereference your type as another type, the compiler can safely use that way---the way *you defined*---where it needs to. As such, this is very different from pointer type coercions in C. There's no unpredictability about what you'll end up with, and you can't do *arbitrary* coercions. And of course, this is what makes it ergonomic to use `String` and `str` side by side: `String` implements `Deref` for `str`, so anything which expects an `&str` can also take `&String` because of this rule. ### The `Mut` variants One thing I've glossed over so far in the discussion is that each of these traits has a `Mut` version: `BorrowMut`, `AsRefMut`, and `DerefMut`. These do exactly what you'd expect: let you implement the *mutable* equivalents to the above. Separating these from the immutable variants might seem like extra work, but actually it's extra control: it means you *can* let consumers have mutable access to your data, but you don't have to. This is particularly helpful where you're defining something with an immutable external API and a mutable internal API. I haven't looked around for an example of this pattern, but I imagine this would be a sensible and fairly Rustic way to implement so-called persistent data structures in Rust. ### An Example For an interesting example of a case where someone is using `Borrow` and `AsRef` in practice, I'll link a blog post by Arnin Roacher from mid-2016, in which he describes building a command line tool for the Sentry crash reporting framework. In that blog post, he describes using a `RefCell` to deal with a C API that expected a single, long-lived pointer for managing a connection. As an aside, if you're looking for a relatively small but solid Rust code base to read through, the **sentry-cli** repository is a great place to start, so I'll link that in the show notes as well. ## Closing I hope that gives you a pretty solid idea of how you can use, and when you should use, these three traits around borrowing and referencing things in Rust. These are a little more arcane than some of the pieces we've talked about before, but they're also incredibly useful---when you want them, you *really* want them. ### Sponsors Thanks to - Chris Palmer - Christopher Giffard - Matt Rudder - Ben Whitley - Peter Tillemans - Philipp Keller - Steven Murawski - Raph Levien - and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website, or if you're a company interested in advertising to developers, please email me! ### Info You can also find links to the docs, repository, and crate page for `quick-xml` at NewRustacean.com. You can follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use. I'd love to hear your feedback, as well as suggestions for topics, interviewees, and so on, in the threads for the episode on the Rust user forum or Hacker News. And hearing from you via email is one of my favorite things---feel free to send me a note at hello@newrustacean.com. Another Rustacean in my vicinity recently sent me a note and we're going to see if we can meet up sometime soon. And hey, speaking of meetups: if there isn't a meetup in your area, you should think about starting one! Jump in the #rust-community channel and they will help you get going. Until next time, happy coding! ================================================ FILE: docs/e019-script.md ================================================ # Let's `Clone` a `Cow`! ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 19: Let's `Clone` a `Cow`!* ### News-y thing One quick note before we jump into the episode: if you hear before March 2017, you should take a look at underhanded.rs, where the Rust Community Team is running a contest to create deliberate vulnerabilities in Rust software, to help improve security all around---which is hugely important, given one of Rust's goals is making more secure software! If that's something your interested, check it out. Now, into the show proper! ### Setup Over the past several episodes, we've been working through some of the different patterns Rust offers us for dealing with managing memory. - In episode 13, we looked at lifetimes---what they are, how to write them, and when you need to write them. - In episode 14, we zoomed in on the details of managing strings specifically. - In episode 15, we looked at *smart pointers*---especially `Box` and the `Rc`, `Arc`, and their corresponding `Weak` types. - In episode 16, we followed up by looking at how we can use the different *cell* types to - In episode 17, we took a step back and just talked about the general syntax and semantics of referencing and dereferencing and the corresponding operators. - In episode 18, we talked about the `Borrow`, `AsRef`, and `Deref` traits. Lots and *lots* of discussion about memory management. That makes a lot of sense: in some sense, Rust's whole reason for existing is that we need a way to manage memory *safely*. But this episode is going to pretty much wrap that up, at least at a first pass, because we'll largely have covered things where memory itself is front and center. To be sure, the topic will continue coming up, e.g. when we talk about the traits for thread safety---but it'll be a little less front and center. In today's episode, we'll tie this up with a bow, talking about the `Copy` and `Clone` traits and the `Cow` type! ## Precursus: more on traits Before we start, though, we need to pause and talk about a few things we skipped over when we talked about traits back in episodes 8 and 9: default implementations, marker traits, and super-traits. ### Default implementations A trait can supply a *default implementation* when the normal or default behavior can be known ahead of time. Most traits don't have these, because in most cases you don't have any way to know ahead of time how a given type will need to implement the interface. For example: equality and ordering, expressed with the `Eq` and `Ord` traits, simply couldn't have default implementations. But on the other hand, there *are* cases---one of which we'll see below---where we can know what a good default implementation is. The current version of the Rust book uses the example of a trait which supplies `is_valid()` and `is_invalid()` methods. You might not know what `is_valid()` should return, but regardless, you can probably assume that `is_invalid()` can just return `!is_valid()`. Of course, implementors need a way to change the implementation if there's a better way to do it. In that validity-checking scenario, for example, it might be the case that you need to do an exhaustive check, but could more cheaply do a sequence of checks and therefore have better best-case performance for calling `is_invalid()` than negating `is_valid()`. In that case, you just add the method definition in the `impl` block like with any other trait method implementation. ### Marker traits When we talked about traits originally, we described them as a way of describing common structure or behavior. However, there is a set of traits which have no functionality of their own, but which simply *mark* the implementing type as having certain properties. There are a number of these traits in `std::marker`, including `Send`, `Sized`, `Sync`, and---important for our purposes today---`Copy`. There are also others elsewhere in the standard library, including the `UnwindSafe` and its buddy, `RefUnwindSafe`, in the `std::panic` module. The idea of a *marker trait* is that it's totally empty, and simply used to serve as a *marker* for some kind of guarantee about a type. You can even implement your own if you have a good use case for it; the aforementioned `UnwindSafe` types aren't built into the compiler but are simply defined in `std`. ### Supertraits Now, what are *supertraits*? Traits in Rust can indicate that they are "subtraits" of another trait. If you've coming from an object oriented background, your first instinct on hearing that might be to think of them as analogous to a *subclass*, but that's not it. Rather, it's like an interface *which extends another interface*. In today's discussion, for example,, we'll see that `Copy` declares `Clone` as a supertrait. By doing that, the `Copy` declaration is actually saying it is *more specific* than `Clone`. That is: all `Copy`-implementors are `Clone`-implementors, but not all `Clone`-implementors are `Copy`-implementors. We'll talk about the reason for that below. You write a sub-trait relationship by using a colon and the name of the super-trait after declaring the trait. So in the case of `Copy`, it's written `pub trait Copy : Clone` and then the (empty) body. There are *many* such sub- and super-trait relationships in the standard library. They're really much the same as any generic type constraint, except that they apply to traits rather than to generics. For example, `Eq` requires `PartialEq`, `Ord` requires `PartialOrd`, and so on. ## `Copy`, `Clone`, and `Cow` ### `Copy` The `Copy` trait applies to types---and here I'm quoting the standard library docs---"whose values can be duplicated simply by copying bits." That's distinct from types whose values *can't* be duplicated simply by copying bits, usually because of some degree of indirection behind pointers. Put another way, these are *simple* types---there are no references to worry about here, because if there were we couldn't just copy the bits. Why that constraint matters, you'll see in a minute when we talk about `Clone`---because `Clone` is a necessary precondition for `Copy`. However, in the normal case, Rust *moves* the ownership of the data whenever it can. Here's an extremely simple example of that (which I've written out in the show notes). Let's say we declared a `struct Point` with `f64` members `x`, `y`, and `z` and an `origin` method `origin` in the `impl`. Then we could declare a point: `let a_point = Point::origin()`. Now, if on the very next line, we write `let moved_point = a_point`, and then try to `println!("{:?}", a_point)`---that is, try to print the original point---the compiler will give us a "use of moved value" error. Rust *moved ownership of the data* from the original `a_point` binding to the new `moved_point` binding. As such, we can't get back to the original binding. This would violate Rust's core rules about ownership---remember, only one binding gets to *own* the data at a time. There are times, however, when we just want to make a copy so that we *can* still access the original value. You can imagine plenty of times when dealing with integers, for example, where you might want to set up the initial value of one integer with the current value of another, but still be able to use the original. This is what `Copy` is for: the case where we want to get the same *values* in a new, owned binding, while leaving the ownership of the original data with the original binding. The big upside is that we can make an assignment and then continue using the original binding. The big downside is that copies can be extremely expensive for very large data structures. Note that this distinction between moving and copying data is a *semantic* rather than a *mechanical* distinction: sometimes, though not always, with move semantics Rust can re-use the same memory space for the next "owner" of the data. That kind of space reuse is a small win for something like an integer, but for some large enum or struct type, it can be a big win, especially over the life of the whole program. That's a nice optimization when it can happen. But most of the time, Rust *does* copy the data over even if when using move semantics. The point of the `Copy` trait is *ownership*, not instructing the compiler how to handle the memory. And that makes sense. After all, if you specifically *need* to reuse the same memory, you can just take a reference! So that's `Copy`. But of course, I brought up marker traits for a reason: namely, that `Copy` is a *marker trait*. All it does is tell the compiler to use copy semantics instead of move semantics with types which implement it. ### `Clone` But this raises an important question: *how* does the Rust compiler perform the copies? After all, if you want to copy the values for anything but extremely simple value types, you have to know *how* to copy them. For example, if there are references involved, making a true duplicate involves following all those references and creating copies of the values behind those references, and then creating new references to those new copies. You may have heard this described as "deep copying" in contexts like JavaScript. The `Clone` trait is the trait which tells Rust how to perform those copies, and so all `Copy` types must also be `Clone` types. Put another way: `Clone` is a supertrait for `Copy`. But `Clone` is also much more generally useful. After all, there are plenty of places you want to `clone()` something while retaining normal move semantics instead of switching over to copy semantics. When dealing with `String`s, for example, it would be extremely expensive to make them `Copy` types: that would mean you *always* made a full copy of a `String` any time you assigned it. That would destroy a lot of the performance wins we all appreciate in Rust. But you do need a way to specify how to get a copy of a `String` when you actually *need* a copy. And of course, it's extremely valuable for there to be *one* way to do that, consistent across a variety of types (even if the implementation details differ on a per-type basis). *That's* where `Clone` comes in. The `Clone` trait specifies two methods: `clone` and `clone_from`. Implementors *must* implement the `clone` method, and *may* implement `clone_from`. I say *may* because a default implementation of `clone_from` is supplied by the trait. The default implementation is just to do a bit-wise copy of all the elements of the type. For many types, that's exactly what you want. But as with all default method implementations, you can override it and implement it yourself if you need to. If you're wondering about the deep copy problem: well, this is why you can only implement `Clone` for simple types *or* types which contain only *other* `Clone` types. There's no way to *automatically* deep-copy reference types unless those reference types *also* define how to clone themselves. However, once you *do* have a type whose members are all `Clone`, you can just use the `#[derive]` attribute (which we talked about in more detail back in episode 7) with the `Clone` trait. And this makes sense: if you know how to `Clone` every member, then `Clone`-ing the type is just recursively cloning its members. In other words, `Clone` is just a normal deep copy---but with Rust's strong type guarantees wrapped around it, and the nice ergonomics of the `[#derive]` syntax sugar. And because `Clone` is a supertrait for the marker trait `Copy`, any type which is `Clone` can be `Copy` for free. And just as any type whose members are all `Clone`, any type whose members are all `Copy` can also be `Copy`. ### `Cow` Now let's pivot slightly, put some of these pieces together, and look at the `Cow` type. In this case a "cow" is not a large, possibly smelly animal, but a "clone on write," or "C-o-w" smart pointer. The `Cow` type pulls together the `Borrow` and `Deref` traits (discussed in episode 18) and the `Clone` trait (which we just talked through). With `Cow`, we have a type that gives you *immutable access* to data you are only *borrowing* access to (using the `Borrow` trait), but lets you get a mutable *copy* of the data if you need to mutate it (using the `Clone` trait). That way, when you have a piece of data where you don't know until runtime whether you'll need to mutate it or not, you can just wrap it in a `Cow`. You can wrap up any other type in a `Cow`, just like you can in a `Box` or an `Arc`. Since it implements `Deref`, it will do that one nice little bit of automatic type coercion the Rust compiler does, and you can transparently use it with functions which expect the wrapped type. Of course, just like with other smart pointers, you have the *small* overhead of allocating a smart pointer on the heap. And you have the potentially very large performance costs of doing a deep copy on a large data structure. But This can make our APIs a lot friendlier. If you're not in a performance critical section of the code, you may not care that much about whether a copy happens when you write something, and accordingly you may not want to have to write `.clone()` every time you need to make a copy and do something with it while leaving the original ownership in place. Under the covers, `Cow` is actually an `enum` with two variants: `Borrowed` and `Owned`. The `Owned` type explicitly wraps around a trait which is *also* called `Owned`, and which is itself (and here I'm quoting the docs again) "a generalization of `Clone`": it not only lets you go from a *reference* to some type `T` to an owned copy of the value of `T`, but also from *any* borrow, including those created with the `Borrow` trait. The `Borrowed` variant of `Cow`, meanwhile, lets the type wrap around borrowed data as well. So `Cow` is general purpose and can be used equally with, for example, a `&str` borrowed type, or with a `String` owned type. Here's the neat thing: we're not working around or dodging the borrow checker somehow with this. We're actually working *with* it. We only ever borrow references to data we need to access immutably. When we get to a point where we find that we actually need to write a change, the `Cow` will automatically run its implementation of `clone` and hand us a *copy* of the data. But the thing that's nice about this is: you don't pay that cost of copying the data *all the time*. You only copy the data when you *change* it. And you're also not paying the ergonomic costs of having to think explicitly about ownership all the time. As long as you consider the performance tradeoffs carefully, though, it can be a win: `Cow` makes for a really nice abstraction. I should also note in closing: `Cow` is pretty straightforward to implement---you can go look at the source (which I'll link in the show notes) and see for yourself. There's nothing magical happening there, and less than 100 lines of *very* readable Rust code to implement the whole thing. ## Closing So that wraps up our journey through single-threaded memory management at a high level in Rust. In the months ahead, I'm expecting to do another interview. I also plan to tackle a question a high-tier sponsor posed about structuring and organizing larger codebases, to talk in some detail about Cargo, and then to dive back down into more nitty-gritty details! ### Sponsors Thanks again---as always!---to - Chris Palmer - Christopher Giffard - Matt Rudder - Ben Whitley - Peter Tillemans - Philipp Keller - Steven Murawski - Raph Levien - and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website, or if you're a company interested in advertising to developers, please email me! ### Info You can also find links to the docs, repository, and crate page for `clap` at NewRustacean.com. You can follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use. I'd love to hear your feedback, as well as suggestions for topics, interviewees, and so on, in the threads for the episode on the Rust user forum or Hacker News. I also love getting email---you can send me a note at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e020-script.md ================================================ # Putting Code in its Place ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast—a 15--20 minute show about learning the Rust programming language. This is *Episode 20: Putting Code in its Place*. ## Structuring Code One of the things that may have thrown you a bit when coming to Rust is thinking about *how to organize your code*. This is—like every episode I put out!—still something I'm getting a handle on myself. But I've picked up a fair bit by reading Rust codebases over the last couple years, even if I don't have anything at that scale myself. And there are some guiding principles we can draw on not only from Rust but from other languages as well as we think about where to draw the boundaries for our modules and our crates. ### Other languages Many of you coming to Rust are likely coming in from a language like Java or C#, where it's extremely common to group your code primarily by *class* or *interface*, and where it's most common for each file to have one class in it. Java has *packages* comprised of many classes and interfaces, and C# has *namespaces* comprised of many classes and interfaces. Rust's modules have some things in common with namespaces, but a couple important differences, which I'll mention below. Others of you are coming from C or C++. C++ often has similar conventions to Java or C# about having one class per file, but the lines are a little blurrier there because C++ doesn't require *everything* to be attached to classes: you can have functions and static items off by themselves when it makes sense. Modules are usually marked off in terms of *compilation units*: basically source files and the things they include. You use header files to define your public interfaces. Rust doesn't have header files at *all*, of course, so there will be some sharp differences here, and its notion of a compilation unit is also quite different: it is the *crate*, not the *file* (though as we saw in episode 6, files are important---and indeed, that's where we'll spend most of our time today). Some of you are coming in from languages like Ruby, Python, or JavaScript, which all have more or less the idea of standalone functions as well as classes. They also have their own distinct ways of structuring and supplying public interfaces to code. In Python, these map to files and directories with a special file in them. JavaScript is similar, but adds the idea of explicit exports from a given file which can be imported into another file. TypeScript further extends that with *namespaces*, which function much like C# namespaces do. The basic structural divisions in these languages include both *modules* and *classes*, and it's fairly typical to have only one class per module in well-organized code in them---and especially, only one *exported* class. This same idea is going to feature in our approaches in Rust. Finally, those of you coming in from the world of strongly typed functional programming languages---Haskell, F#, etc.---will primarily be used to organizing things into related data structures and functions designed to operate on them. (This, I admit, is the area where I have the least experience, though I remain very interested in using these languages more actively.) And this approach, too, features fairly clear in Rust, just with its own twist. Indeed, it's fair to say that Rust has taken the tack of trying to pull the best ideas from each of those other organizational systems and then mix them into a form that feels nicely Rustic in its crates-and-modules system. ### Rust As we talked about all the way back in episode 6, the basic units of organization in Rust are *modules* and *crates*. Crates are both the overall unit of compilation and the overall unit of *functional separation*. The time to break things out into distinct crates is where you can see a given chunk of functionality being reused across more than one project. For example, small though it is, I may eventually pull the YAML metadata extractor I've written for Lightning (and about which I'll have more to say below) into its own little crate: I'm certainly not the only person out there who might find it useful to extract YAML metadata from a Markdown document. On the other hand, the vast majority of the implementation details of Lightning will be specific to it and won't be readily reusable. I will take this opportunity to rave about Rust's crate system again for a moment before moving into the nitty-gritty details of how to structure the modules within a crate, though. The more time I spend taking advantage of crates.io and Cargo, the more grateful I am to have it. In C and C++, because they have historically lacked a good story for managing *packages*, it has often been painfully difficult to do that kind of extraction work---I've seen it be much easier in practice to simply copy-and-paste code into another codebase than to try to manage them as separate libraries, simply because there isn't a good way there to deal with version locking or those kinds of concerns. You can do it... but it's painful. Cargo for the win. Now, onto talking about how we organize our crates within modules. Here I'm looking not so much at the mechanics, which I covered in some detail back in episode 6, but in terms of *philosophy*: what do we put where, and why? First, though: one clarification I should add to those details from episode 6, given my references to C# and TypeScript above, though: there is one major difference between the C# or TypeScript namespaces in C# or TypeScript and Rust modules. C# and TypeScript allow you to extend namespaces in various places. A Rust module is only defined in a single place---either in a file, or in a `mod { ... }` block. This doesn't end up being that much of a problem, though: it's not that common (at least in my experience!) to want to extend a given namespace, and since (as I discussed in more detail back in episode 6) you can re-export items in other modules. And I like the tradeoff: extending namespaces from arbitrary locations---rather like monkey-patching a class or object in a dynamic language---has some serious downsides in terms of clarity and expected behavior. But the big analogy to namespaces is there: both are ways of providing a space that *isn't* just a data structure for a given name to live. `Metadata::parse()` could mean a lot of things: `item::Metadata::parse()` tells us a lot more. In any case, this leads us to an important point we need to have in mind when designing the structure of our modules in Rust. Rust *data structures* (`struct`s and `enum`s) are open for extension (via the trait system), but its *modules* are not: the interfaces they export are the interfaces they export, and that's it. You can't reach into them and pull things out they don't choose to expose. Those of you familiar with popular tenets of object-oriented programming may recognize that this has important consequences in terms of "information hiding." Put another (and in my opinion better) way: since not only data structures but also *modules* have public APIs, we have considerable flexibility in designing the our APIs. We have considerable flexibility in what we make private and public---we don't usually feel the need Java's `friend` or the more general `protected` modifier which sits between `public` and `private` in class-structured languages. Instead, you can have a struct with public fields and access those fields freely throughout the module---and all you need to do to prevent other modules from using it is... nothing. You just don't write `pub` in front of the struct declaration, and it's invisible to anything outside the module. This gives us as much granularity and flexibility as we could wish for. ### Putting it together Now, given *crates* as compilation units and *modules* as namespace-like divisions of responsibility, we can now talk about how we want to structure our code across those various divisions. I'll sum this up by saying the basic principle is "think about boundaries in terms of responsibility." That is, of course, an obnoxiously general and vague principle, but I think one of the challenging things about this topic in *any* language is that it isn't obvious. The two most difficult problems in computer science may be naming things, cache invalidation, and off-by-one errors, but *organizing your code* has to be in the top ten. One reason we make such a big deal out of things like the Single Responsibility Principle---and one reason we have to come back to it over and over again!---in the context of Object Oriented Programming is that it's a lot of work determine what the sole responsibility of a given `class` actually is! And the same challenge confronts us here. The fact that we group by module rather than by class doesn't change the fundamental difficulty of the task. But with that as our guiding principle, here are the basic ways *I* think about breaking apart my code in Rust (and, for that matter, a lot of times in TypeScript or JavaScript, too). First, I just try to group closely-related data structures and associated functions. Rust's `impl` blocks go a long way toward making that straightforward in most cases, of course. But even where I have a function which isn't in an `impl` block for a given data structure, e.g. a function which is associated with *more than one* data structure and doesn't logically belong to one of them in particular, I'll try to keep that close to where one or the other of the data structures are contained. Many times, that'll be in a module which is parent to the two modules which define those data structures. And that takes me to my second habit. In general, I tend to want one *public* `struct` or `enum` per module. That's not a hard and fast rule, but it's a habit I've maintained not only in Rust but also in JavaScript and TypeScript over the past couple years with very good results. In my experience, it makes it fairly obvious where to draw the lines, *most* of the time... at least, once you have a good handle on what the data structures themselves should be! Beyond that, there may be any number of *internal* data structures beyond that, but there's actually a really good reason for the one-class-to-one-file structure that's normal in e.g. Java. That reason is that *data structures* are the fundamental things we're dealing with day to day, and an enormous amount of the work we're doing is about transformation of data from one structure to another. So, for example, in my Lightning static site generator project, one of the things I've been slowly plugging away at in the last couple weeks has been doing metadata extraction: given a block of YAML metadata at the top of a Markdown item, I want to extract all of that data. I'm dealing with two data structures there: a source file---which is just a big `String`---and an output structure of a `struct` consisting of the extracted metadata. So the things this module exports are that metadata `struct` and its implementation. There's also an associated `enum` type which is a *child* of that `struct`, which is also exported, as it has to be: you can't "leak" a private type. That right there is basically the only exception to my "only export one data structure from a module" habit. But the idea remains the same: I try to only export one *top-level* data structure from a module; any other data structures exported are pieces of that top-level structure. As an aside, and amusingly---at least to me!---it was articulating this for this episode which helped me realize that I'd drawn the lines in the wrong place: prior to thinking this through, I was treating all the metadata pieces as part of the *item* logic, and accordingly the module was `builder::item` but it actually needed to be at `item::metadata`. There are two reasons for that. First, although the site builder needs to know about items, items are really their own domain, and it's conceivable that I might want to use that data structure elsewhere and for other reasons. Second, item `metadata` is its own concern and has its own data structures, which `item` in turn can *use*. It's subsidiary concern of items. Finally, this brings us to the fact that "parent" modules may want to export some of their children items for convenience in terms of API design. I *could* make myself write `item::metadata::Metadata::parse_from_str()` anywhere I need it... but that's rather needless. Instead, right now I'm doing `pub use metadata::{Metadata,ExtraMetadata}` in the `mod.rs` which defines the `item` module, so that a caller can do `item::Metadata::parse_from_str()` instead. As a rule, the only modules which I let export more than one (primary) data structure will be those kinds of parent modules. Note that I do therefore distinguish between data structures *defined and exported* by a module, and data structures *re-exported* by a module for convenience. The former is an organizational and division-of-concerns question; the latter a question of the ergonomics of *using* the module. And it's worth noting that those *are* different concerns. How I want to consume a module is different from how I want to think about the separation of concerns within my codebase. They're related, of course. You can't talk about separation of concerns without considering how the pieces will be used. In the end, it's possible I won't be exposing metadata distinctly from the `Item`s which use them (though, they'll still be exported in order to be attached to any such `Item`). But having them in their own module allows me to deal with concerns that have nothing to do with Markdown parsing: extracting YAML metadata from the top of the block and converting it to the kind of `HashMap`-based structure I need is totally distinct from converting the body of the item from Markdown to HTML. So in that sense, I separate my code into *modules* based on the Single Responsibility Principle, much as you might with classes in a class-oriented language. Let's summarize, then: - *modules* are the fundamental unit of organization in Rust. - modules should group closely related data structures and functions - modules should normally only export one primary data structure - *crates* are for whenever you need to reuse a given module across more than one project Remember: this is more something I've felt my way to than something I think you should treat as a hard and fast rule. But hopefully it serves as a helpful set of guidelines for starting to think about the structure of a Rust codebase---even if you end up adapting it yourself as you grow more experienced. ## Closing Today's episode was brought to you specifically by Christopher Giffard. One of the higher sponsor tiers on my Patreon page includes getting to pick a topic, and this was a point of interest for him. Thanks, Christopher, both for sponsoring and for prodding me to think on this! ### Sponsors Thanks to - Chris Palmer - Dan Abrams - Daniel Collin - Matt Rudder - Ben Whitley - Peter Tillemans - Philipp Keller - Raph Levien - and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes. And thanks to my friend Ben Makuh for helping me come up with the punny title! (Seriously, people: I spend a ridiculous amount of time trying to think of good titles, and my slightly sick self was not getting there today.) If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website, or if you're a company interested in advertising to developers, please email me! ### Info You can find show notes with links, code samples, and more at NewRustacean.com. You can follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use. Until next time, happy coding... and giving back! ================================================ FILE: docs/e021-script.md ================================================ # Keeping your types under cover ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast: a show about learning the Rust programming language. This is Episode 21: "Keeping your types under cover". ## Overview Today we're going to take a step back and look at a couple relatively easy tools in Rust. These are some of my favorite kinds of things in programming languages: tools which are not at all complicated or arcane, but which make the experience of programming in the language *much* better in some way or another. Today, we're going to talk about two different kinds of type declarations: *type aliases* and *new types* -- with a couple variations on how we can build the latter. ### `type` declarations Let's start with `type` declarations. The simplest kind of type declaration is something like `type Email = String;`. That defines a type you can use throughout your program, `Email`. This is a really convenient way of making your types more descriptive. After all, there are *lots* of kinds of `String`s out there, and giving things good names is a really helpful way of clarifying exactly what you mean. Instead of being left wondering, "Is this an email or a name?" the type itself can express some of that intent. Now, one important thing to understand is that type aliases are tools of convenience, *not* of type safety. When you write `type Email = String;` you're not creating a special type. *All* you are doing is creating a nickname for the longer type. If you're coming from Haskell, this is *not* a newtype, in other words. I have often wished there were a native facility for doing newtypes in Rust, because usually when I create this kind of thing in my own code it's *not* for a shorthand version, but because I actually want some type safety around something. More on that in a moment. Still, these kinds of things can be extremely helpful: even where you're perfectly fine accepting the type being aliased, you have now expressed to whoever is reading your code the actual *point* of that particular type. For example, we might have a function that sends an email; but let's say that in this particular context we have a good reason to name the function `send_message`. (This is a slightly silly example, as `send_email` would normally be a better name. But I'm using it to illustrate the point more clearly.) In that case, we might have a function definition something like: ```rust fn send_message(toAddress: Email, content: String): Result<(), ErrorCode> { ... } ``` It's really obvious even just looking at that signature that there's supposed to be a difference between the `toAddress` parameter and the `content` parameter, because their types are named differently. Now, of course, a caller could still get that wrong (and we have a solution for cases where we want to make sure the caller *can't* get this wrong, which we'll come back to in a few minutes). But at a minimum, the type signature makes it *even more* explicit what kind of thing we have here. It even clarifies that sending this message will send it specifically to an *email* address, not a physical address. So it's a real win even in this simple and rather silly example. Of course, precisely because this example *is* rather silly, it may not be obvious where you'd really want to use something like this: aliases for `String` might clarify your intent slightly, but good function and parameter names are actually probably *more* helpful here. The biggest places in Rust where these kinds of things are useful are type signatures you have to repeat a lot; and *complex* type signatures. Let's start with often-repeated type signatures, and with a type alias you're almost certainly familiar with if you've spent much time with Rust: `std::io::Result`. Normally, the `Result` types have two type parameters, `T` for the type returned in the success case, and `E` for the type returned in the error case. However, `std::io::Result` has only *one* type parameter: `T`, for the expected type. That's because `std::io::Result` is a type alias for `Result`. Since all errors in this case will be of the type `std::io::Error`, we don't need to make users (or the standard library team, for that matter!) type that out anywhere they want to return a `Result` within `std::io`. They can just write that it returns a `Result`, for example, instead of a `Result`. To make this work, we just write a generic type alias: `type Result = Result`. If you look in the Rust docs or source, in fact, that's almost exactly what you'll see. (The only difference is that the full namespace isn't written out because the `std::io` namespace is already in context.) Another way to think about this is that we're making a generic type more specific. `std::result::Result` can take *anything* as its type parameters. `std::io::Result` can take anything for that `` parameter, but it's much more specific than the `std::result` type, because it always and only returns `std::io::Error`s for its error type. The other major scenario we care about is when we have a complicated type that we just don't want to write out over and over again. It's not hard to bump into these in Rust, *especially* when dealing with smart pointers. Imagine you have an `Arc>`. Even though it's a totally concrete type (no generics in sight), you *really* don't want to have to write out that whole type every time. Or at least, *I* don't. So instead you could give that a good, local name. The type would still be exactly the same, but you could always just use the type alias instead. You could name it `ThreadSafeCollection` and just say *that* anywhere you need it, and it simplifies your codebase enormously. Now, I want to pause for a moment before moving on to "new types" to trace out an implication of the fact that these really are just convenient names for longer types. Because that is the case, *any* function that works on the full type name also works on the type alias. That ends up being particularly handy when dealing with things which implement traits like `Iterator`: if you can `map` over the type being aliased, you can `map` over the alias too. ### New types All well and good: those use cases really are important. But what about the times when we *don't* want the original type to be interchangeable with the new type we're defining? I used the example of an email address initially, and we might well want to distinguish between an email address and a more general string. This is where Haskell's newtypes come in handy, but it's the only language I know of that has them. Most other languages in the same broad lineage as Rust have a nice, low- or no-cost way to accomplish the same thing, though, and Rust is no exception! We have two closely related ways to create types which are *distinct* from a type-checking perspective this way. One is a *tuple struct*; the other is a *single-case enum*. They have the same result: they just wrap another type in a distinct type declaration. #### Tuple structs For a tuple struct, you'd write that like: ```rust pub struct EmailStruct(String); ``` Then you can declare an instance by writing: ```rust let address = EmailStruct("hello@newrustacean.com".into()); ``` (Recall that `.into()` takes the string literal, which is a string slice reference, and makes it an owned `String`.) When you *used* the address, you can destructure it. Say we were using an external email library which had a `send` function which just took a string. To unwrap it, we could either just use the `.0` accessor, or (my preference), explicitly destructure it. #### Aside: destructuring assignment We haven't talked about destructuring assignment before, though, so before I *do* it, let's pause and talk about what it *is*. Destructuring assignment uses the same kind of syntax as pattern-matching, but outside the body of a `match` expression. It lets you bind directly to any public member in the interior of a struct or enum variant. (Note, though, that you *can't* do this enums outside the single-variant case, because you have to match against all its variants.) It's incredibly handy for getting at internals of a given type without writing something like `let the_value = the_instance_of_the_type.the_value`. Going back to our `EmailStruct` example, that would look like this, recalling that we'd created an `address` variable with the value attached: ```rust let EmailStruct(emailString) = address; send(emailString); ``` Delightfully, I wasn't exaggerating when I said destructuring assignment has the same syntax as pattern-matching arms; I was being exact. That means that any kind of destructuring you can do in a pattern-match, you can do here. So let's say we had a more complicated `struct`, one with a couple fields: ```rust struct ThingToDestructure { a_field: String, another: i32, } ``` We could declare an instance like usual: ```rust let thing = ThingToDestructure { a_field: "Neat!".into(), another: 42, }; ``` Then we could destructure it – and, handily enough, we can rename things in pattern matches. So, for example, if we didn't want to use `another` locally, we could call it `can_rename` instead: ``` let ThingToDestructure { a_field, another: can_rename } = thing; ``` Destructuring assignment isn't necessarily something you need *all the time*, but when it's handy, it's *very* handy. #### Single-variant enum Now, back to the main topic – what about the other way of building special types? Well, for a single-variant enum, you'd declare it by writing: ```rust pub enum EmailEnum { Address(String), } ``` Creating an instance of the num is just like creating any other enum instance: ```rust let email = EmailEnum::Address("hello@newrustacean.com".into()); ``` Notably, however, you can use destructuring assignment here just like in the struct tuple case, *because* it is a single-case enum: ```rust let EmailEnum::Address(emailString) = email; send(emailString); ``` You can probably tell even just in listening to me walk through those verbally that you're basically always better just using a tuple struct in these cases. There's a lot of extra keyboard mashing involved for no actual gain by using an enum in this case. I brought it up for two reasons, though: first, simply so you know what you're looking at if you happen to bump into it; and second, because if you're coming from another language with tagged unions (F♯, Elm, etc.) that might be your first inclination, since that's how you usually do it there. And it does *work* in Rust. There's just no reason to do it here, since we have tuple structs available. Now, there are a couple other extra challenges we face when defining a custom type like this. One is that, unlike a type alias, you don't get all the various implementations which apply to the inner type for free. You can implement them *fairly* easily, of course -- I provided a simple example of implementing `Iterator` in the code samples for this episode so you can see how it might work -- but you *do* still have to implement them yourself. And that does dramatically decrease the convenience. So you'll have to evaluate whether the work of implementing those APIs yourself is worth the extra type safety you get from defining the type as a tuple struct rather than just a type alias. And it won't always be obvious. Now, one thing you *can* do when implementing a newtype is implement the that sometimes you want all this type safety *and* want to be able to use the underlying type in some places. You can implement the `Deref` trait, so that calls can take advantage of deref coercions. In our email address example, then, we might implement `Deref` for the `EmailStruct` with a target type of `String`. Because `String` in turn implements `Deref` for `str`, you could then pass your `EmailStruct` *by reference* to anything which expects a `&String` or (more likely) `&str`. Similarly, if you wanted to be able to move the contents out of the struct into an email, you could implement `Into` for `EmailStruct`, and then anywhere you were ready to move ownership into something that required an owned `String` you could just do `address.into()`. Of course, you should be careful with these kinds of tools: it's easy to actually just end up throwing away a lot of the type safety you're trying to buy yourself with these kinds of "new types" in the first place. But you at least have the option. My rule of thumb for these kinds of things (across languages) is that the more critical to the business rules something is, the more likely I am to write a real type and whatever custom implementations I need. By contrast, where it's just a convenience issue -- I don't want to write that same long type signature with multiple layers of generics over and over and over again -- I'm happy to use type aliases instead. ## Outro That's about all there is to say about type aliases! They're a really handy feature, but they're not an especially *complicated* feature. Hopefully you'll get some good mileage out of them! Thanks to this month's $10-or-more sponsors: - Anthony Deschamps - Chris Palmer - Behnam Esfahbod - Dan Abrams - Daniel Collin - David W. Allen - Matt Rudder - Peter Tillemans - Philipp Keller - Raph Levien - and Vesa Khailavirta As always, thanks as well to everyone who helps other people find the show---whether by just telling a friend, or by rating or reviewing it in iTunes or recommending it in another podcast directory, or by sharing it on social media! You can find show notes for this episode, including code samples for everything I discussed, at newrustacean.com/show_notes/e02. The show is on Twitter @newrustacean, and I am @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or – and this is my favorite – just send me an email at hello@newrustacean.com. Until next time, happy coding. ================================================ FILE: docs/e022-script.md ================================================ Full script for the episode. # e022: `Send` and `Sync` **Note:** In the original (recorded) version of the episode, I said "deadlock" everywhere I meant "data race." Throughout the transcript, I've made the substitution accordingly, but if you're listening to the episode, you'll have to do it mentally. Sorry about that! ## Intro Hello, I'm Chris Krycho and this is New Rustacean: a show about the Rust Programming Language and the people who use it. This is episode 22: TODO There are a few major parts of Rust we haven't covered yet, including one of the most important _parts_ of Rust's promise: safe concurrency. So today we're going to dive in and talk about the two traits that are the most important part of Rust's story for enabling safe concurrency: `Send` and `Sync`. ## Background Multithreaded processing has become increasingly important over the last couple decades, as our ability to speed up single-threaded processing has effectively hit a wall. We _can_ make things go faster, but it takes a lot of power and it generates a lot of heat, and that makes it hard to speed up our programs just by running the processor faster. Starting in the early 2000s, the computer industry began adapting to that by allowing for multi-threaded and multi-processor approaches, which at least in principle lets us parallelize parts of whatever we're working on. But there's a problem: parallelizing things effectively is _hard_. And it's hard in at least two ways—one of which Rust really _can’t_ help us with, but one of which it really can. * Rust _cannot_ help us with designing algorithms well for parallelization, or even with identifying which specific problems are amenable to parallelization. We still need good old computer science reasoning for that side of things. * On the other hand, Rust _can_ hep us make sure the design we implement is safe once we _have_ identified candidates for parallelization. In fact, it can do more than help. Rust can actually just eliminate whole classes of parallelization bugs common in other languages, and do so at compile time. This is basically true of _all_ the ways Rust helps us, to be fair: it doesn’t tell you how to write an algorithm that performs linearly instead of quadratically. It makes it easier to not shoot yourself in the foot with memory errors while you write your algorithm. The same thing goes for parallelism. So now we know _why_ we care about `Send` and `Sync`—what are they and how do they work? ### Marker traits The first thing we need to understand is that both `Send` and `Sync` are _marker traits._ This is one of several things I passed over in my previous discussion of traits back in episode 8; we’ll be coming back to many of them in the next few months. A _marker trait_ is a trait which does not have behavior of its own; it simply specifies that certain kinds of invariants are enforced, which the compiler can then require types to implement before it will allow certain kinds of behavior. These are not _special_ in that they’re not restricted to language built-ins or anything like that. You can implement your own and define what makes that trait hold or not in your own code, and get the same kinds of guarantees. (For an example tied to a recent episode, Diesel actually uses marker traits internally – for example, to [segregate certain kinds of SQL expressions](http://docs.diesel.rs/diesel/expression/trait.NonAggregate.html 'NonAggregate') from each other.) In the standard library, though, there are four of these market traits: `Copy`, `Send`, `Sized`, and `Sync`. There’s also the `PhantomData` struct type. We’ve already seen `Copy`, in episode 14’s discussion of strings, and we’ll come back to `Sized` and `PhantomData` in the future. For today, we’re just sticking with `Send` and `Sync`. There are two fundamental things you need to understanding about `Send` and `Sync`. 1. They are automatically implemented for every type they can be by the compiler—they have default implementations, and you have to explicitly opt _out_ of those if you’re somehow doing unsafe behavior yourself. For example, the `Rc` type expressly indicates in its own type definition that it is _not_ `Send` or `Sync`. 2. Closely related to that first point: `Send` and `Sync` are _unsafe traits_. This means that you cannot implement them “safely” – and that’s fine because your safe types will basically get them for free. You need to write the `unsafe` implementations of any `unsafe` type machinery you intend to be `Send` and `Sync` _very_ carefully, to guarantee that the relevant invariants hold (i.e. that you can’t get data races etc.). We’re not going to dig further into the details of _how_ you set up those invariants on your types today—it really only matters when you’re building your own implementations which are necessarily in the “trust me, I know what I’m doing category” of `unsafe` code, because they’re _unsafe traits_. Instead, we’re just going to talk about what the two traits are and then look at how we can put them to use together. However, you should note that if you _do_ need to implement a new, low-level type which is `Send` or `Sync`, the responsibility is all on you to get the implementation right, as it is with `unsafe` code in general. (We’ll cover `unsafe` probably in early April.) ### `Send` and `Sync` `Send` is the trait that indicates it’s safe to _move_ data across threads. `Sync` is the trait that indicates it’s safe to _share_ data across threads. Put another way: `Send` is about _cross-thread ownership_, and `Sync` is about _cross-thread borrows_. A type `T` needs to be `Send` to be handed to a cross-thread function with a signature like `fn do_something(with_a_t: T)`. A type `T` needs to be `Sync` to be handed to a cross-thread function with a signature like `fn do_something(with_a_t_ref: &T)`. Once that distinction is in place, the normal rules about mutability and access apply, just as they would in a single-threaded context. So what makes a type `Send`-able and `Sync`-able? #### `Send` rules For a thread to be `Send`, it has to be For more complex types – structs, enums, and smart pointer wrappers around them – as long as all the pieces that make up the type are _also_ `Send`, the type is automatically `Send`. If any of the struct members or enum variants are _not_ send, the type as a whole not `Send` either. #### `Sync` rules The briefest definition of `Sync` – and here I’m stealing straight from the standard library docs, because they’re really good! is that a type `T` is `Sync` when the type of a _reference_ to `T`, `&T`, is `Send`. (This is why we’re talking about the two in the same episode: not only are they closely related conceptually, they’re closely related in terms of their implementation.) To expand that out a bit, let’s thing about `String`. Remember that a `String` is a smart pointer, which is ultimately just a `Vec` of bytes which has some guarantees in construction so you can be sure that it’s always valid UTF-8. (If you need to brush up on strings, you can go back and listen to [episode 14](https://www.newrustacean.com/show_notes/e014/index.html 'e014: Stringing things along'), where I talked about them in some detail.) When you take a reference to a `String`, you get an `&String`, but most of the time you actually get a reference to an `&str` slice type. If `&str` or the under-the-hood `&Vec` which `&String` is a special case of were _not_ safe for `Send`, then `String` would not be `Sync`. But since string slices and references to `Vec`s are carefully implemented by the standard library to make sure they _are_ thread-safe, you can use them this way. As a result, the exact same rule applies for `Sync` types as for `Send` types: as long as all components of the type are `Sync`-safe, so is the type itself, no matter how complex; but if any of the parts of the type are _not_ `Sync`-safe, neither is the type itself. #### Other data structures Of course, this isn’t all there is to say. We can also combine these with other data structures and traits we’ve talked about in the past, when we need other kinds of behavior. The strategy is to build up our abstractions from the specific, lower-level combinations of types we need. For example, we might need a reference-counted piece of data that’s shared across threads, and which needs to be possibly owned by more than one thread. With today’s context in mind, we now know that we can take a piece of data that’s both `Send` and `Sync` and put it in an `Arc`—an atomically reference-counted smart pointer type, which we talked about briefly in an earlier episode. Part of what makes `Arc` especially useful is the guarantee we talked about above: any type whose contents are all `Send` or `Sync` are themselves automatically `Send` or `Sync`. That means that any `Arc` which wraps a `Send` and `Sync` type is automatically safe to use across thread boundaries. And the fact that that’s _not_ true for `Rc`—because it’s not an atomic type and doesn’t maintain the right invariants for thread safety itself—is what makes `Arc` appropriate for cross-thread work and `Rc` inappropriate for it. Put in the terms I used earlier in the episode: `Arc`’s (internal, `unsafe`) implementation maintains all the invariants we need; `Rc`’s implementation _doesn’t_. ### Using `Send` and `Sync` data Once you have a piece of data that is `Send` (and `Sync`) you can use them in contexts where you’re doing multi-threaded work. For a fairly easy-to-understand example, let’s imagine processing hundreds or thousands of Markdown files. Since each file is independent of the others, we decide this problem is ripe for parallelization. Now, I want to say up front: what I’m about to desscribe is definitely a naïve approach, and in anything remotely approaching a real-world scenario we’d want something like a thread pool to avoid totally hammering our machine. There’s a great discussion of this in ch. 20 of the second edition of the Rust book, so if you want to see how to do this _right_! Props to Steve Klabnik and Carol Nichols-or-Goulding for their write-up there. Listeners who have followed along with previous episodes will note that we could also sort of cheat and just use Rayon for multi-threading parallelism, but that wouldn’t help us see how `Send` and `Sync` come into play more manually. In this case, we might have a function `markdown_to_html`, which just takes a string buffer – an `&str` – as its argument. We could just iterate over a `Vec` of `String`s representing the Markdown files and pass them to `markdown_to_html` in sequence. But we want to parallelize them, so instead we’d chunk up the vector into something like the number of processor cores on our machine, and then iterate over those chunks. With each of them, we’d then use the `std::thread::spawn` function to spin up a new thread, and pass it a closure to execute. That would read _something_ like this, if we had a current Markdown item named `md`: ```rust,ignore let first = std::thread::spawn(|| markdown_to_html(&md)); ``` We’d do the same with the others, and push them into some other container to look them up later, and once we finished iterating through everything, we’d call `join` on the thread references we saved, and every time we did we’d get back What’s interesting here isn’t so much the `std::thread` APIs – though it’s nice to have at least mentioned them explicitly on the show now! – as it is the fact that all of this can be _guaranteed_ to be thread-safe by the compiler. If we tried to hand over a mutable reference to, say, the `Vec` itself on each pass through, we’d get the usual Rust complaints about there being more than one mutable reference at the same time – no different than any other context! But if for some reason (and there are lots of times this might come up!) you were wrapping each Markdown buffer with a type which was thread-unsafe – say, a `Cell` or `RefCell`, with their _non-atomic interior mutability_ – the Rust compiler would say, “NOPE. You can and will end up surprising yourself in a painful way with those via data races or overwriting mutable data or something like that, so you’re not allowed to do it.” When that circumstance comes up, you just have to switch to another strategy – if you need interior mutability, to something like `Mutex` or `RWLock` or one of the `Atomic` types if you’re getting really down into the nitty-gritty. ## Outro So now we have a pretty good starting idea how to deal with multi-threading and parallelism in Rust. Again, most of the time unless you’re implementing your own abstractions you’re actually better using one of the existing community libraries for parallelism – Rayon, which we’ve talked about in the past, or Futures and Tokio for async I/O, which we’ll talk about in the future – being the big ones. But now you know the machinery those use “under the hood,” and that’s an important part of understanding how they work and what their performance characteristics will be, and therefore when each is appropriate! ### Sponsors Thanks, as always, to all of this month's sponsors. Contributors who gave at least $10 included: * Aaron Turon * Alexander Payne * Anthony Deschamps * Chris Palmer * Christopher Giffard * Behnam Esfahbod * Dan Abrams * Daniel Collin * David W. Allen * Guido Hoermann * Hans Fjällemark * Hendrik Sollich * John Rudnick * Matt Rudder * Nathan Sculli * Nick Stevens * Peter Tillemans * Olaf Leidinger * Oluseyi Sonaiya * Raph Levien * Shane Utt * and Vesa Khailavirta If you're enjoying the show, please let others know about it in person or on social media, rate and review in your favorite podcast directory, or, if you're feeling extra generous, by sending some financial support for the show my way at Patreon.com/newrustacean or as a one-off via any of a number of other services I've listed on the show website: newrustacean.com. NewRustacean.com also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e023-script.md ================================================ # e023: Traits Deep Dive, Part I ## Intro Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is episode 23: – the first of two deep-dive episodes on traits. Much earlier in the show (all the way back in episodes 8 and 9), I talked about interfaces at a high level: what they’re for, and how you can implement existing traits. Today, we’re going to dig into some of the mechanics of actually using traits – the nitty-gritty of building your own traits and the concrete limitations on where and how you can implement them, and what you have to do to use traits defined elsewhere. In the next episode, we’ll take a look at the use of traits in place of either concrete types or generics, including a look at the `impl trait` feature that will be landing in Rust 1.26! ## Traits: Deep Dive, Part I For a quick refresher, let’s review what traits are *for*. Traits are Rust’s primary mechanism for *shared behavior* between objects. Some languages solve this problem with inheritance, or with interfaces that must be applied to an object at the time of definition. Rust has no conventional notion of inheritance, and its traits are quite unlike, say, interfaces in C♯. A Rust trait defines *shared behavior* only; it cannot define the required *shape* of an object which implements it (e.g. required class fields in traditional OOP language’s interfaces). And a trait can be applied to a type totally independent of the normal definition of that type – you can apply anyone else’s traits to your own types, and your types to anyone else’s traits. And the only place that Rust *does* get something kind of like inheritance in the normal sense is in traits themselves: a trait can declare that implementing it requires that you implement some *other* trait as well. So if you’re coming from the perspective of a Java or C♯ or even TypeScript, traits are sort of like method-only interfaces which can be implemented *whenever*, not just at class definition time. Importantly, as we’ll cover in a minute, they can also be applied to any old type – an `enum` is equally valid for a trait implementation as a `struct`. Traits are *everywhere* in Rust programming, as you can imagine, and the things you can do with them are pretty amazing. So… how do we use them? ### Defining and implementing traits Let’s start by looking at how you actually define and use your own traits. A trait is always defined using the trait keyword and a block that defines the *items* associated with that trait. (This idea of “associated items” is actually pretty large, and it’s also very important, so we’ll come back to it in a later episode. For now, we’ll leave aside some of those details and just focus on creating and implementing traits.) #### The basics Let’s define a slightly silly trait as the basic example we’ll build on for the rest of this episode: `Eatable`, to represent things we can eat. (Apparently I’m writing this episode too close to dinner time!) Anything which implements `Eatable` must have an `eat` method, which returns a description of the act of eating that particular thing. We’d write that like this: trait Eatable { fn eat(&self) -> String; } A couple things to notice about this: 1. The function type isn’t explicitly declared as `pub` or any other privacy modifier. And it’s not allowed to. The trait itself can be declared with whatever privacy you like, but items *on* the trait are always public to whatever implements them. This makes sense when you consider that the whole point of a trait is to define what behavior is available for things *outside* a struct or enum to do. Private details of a type don’t belong on a `trait`; they belong in the `impl` block for the type itself, with whatever privacy is appropriate. 2. We have not defined any implementation. We’ve simply written out the type of the function which any implementor has to provide. However, we could have written a basic implementation – albeit, one that doesn’t know anything at all about the type where it’s implemented, and so it can’t say anything that depends on the internals of those types. ```rust,ignore trait Eatable { fn eat(&self) -> String { String::from("Open mouth, insert food!") } } ``` Now, implementors can just write `impl Eatable for MyFood {}` and then they can call `MyFood.eat()`, and we’ll get back the string `"Open mouth, insert food!"`. However, it’s often preferable *not* to use a default implementation for a trait, even when it’s defined. In that case, we can supply our own implementation. Implementing a trait simply means doing `impl TheTrait for TheType` and supplying all required (and any desired optional) elements of the trait. Let’s say we wanted to make a `Breakfast` type – that sounds nice and “eatable.” One thing that’s worth noting, and which I did not realize immediately when I first started learning Rust a few years ago is that you can implement a trait for *any* kind of type – in other words, for enums as well as for structs. So let’s make a `Breakfast` enum with only the sugariest foods: ```rust,ignore enum Breakfast { Waffles, Cereal, Pancakes, } ``` Then we can implement `Eatable` with some special behavior for this type: ```rust,ignore impl Eatable for Breakfast { fn eat(&self) -> String { match *self { Breakfast::Waffles | Breakfast::Pancakes => String::from("Pour syrup, consume"), Breakfast::Cereal => String::from("Add milk, then enjoy the crunch"), } } } ``` This is what is called *specialization*: instead of just accepting the default implementation of a trait, we’re specializing it for just this one specific object. And we can see even from this silly example why we would want to do that. Remember: the default implementation of the trait didn’t know anything about the actual types that would implement it. And even though we can supply *some* more information about the implementing type with further details in a trait’s definition—we’ll see that in a minute—it’s often the case that a specific concrete implementation will know more about the best way to handle a given trait than the trait itself ever could. A common example of this that you’ll see often is with the `Iterator` trait: although there are default implementations for most of the methods on the trait, you will sometimes see more specific implementations associated with particular data types. In that case, it’s often for *performance* reasons. Because you implemented the data structure, you may have more insight than `Iterator` does about the best way to implement some of the methods. For example, the `skip` method might naïvely be implemented as just calling the `next` method the number of times you pass to it. However, if you have a data structure where every item is of a known size, and laid out in contiguous blocks of memory—like a C-style array, for example—you could write a `skip` implementation that simply jumps to the appropriate memory offset from the current position in the structure. #### Other methods Now, I just implied something very important there: any trait method can call any *other* method defined on the same trait. So let’s say our `Eatable` trait should also describe how the food needs to be prepared. And this one we *cannot* have a default implementation for – some foods are meant to be eaten raw, for example, while others might actually be poisonous if you don’t cook them! So we’ll add a corresponding function to the trait, `prepare`, and we’ll also go ahead and update our default implementation to include preparing. ```rust,ignore trait Eatable { fn prepare(&self) -> String; fn eat(&self) -> String { self.prepare(); String::from("Open mouth, insert food!") } } ``` Now we’ve required that every implementor supply an implementation of `prepare`. It’s totally fine for the trait to do this, because it *knows* that no implementor can exist which *doesn’t* have the `prepare` method defined. This is how a the default implementations for the `Iterator` example can work: they know there is a `next` method defined, and they can define their own default behavior in terms of that `next` method (and one other piece of information we’ll talk about in just a second) – and that’s all they actually *need*. #### Other items on the trait Now, about other pieces of information… I’m not going to take a *lot* of time on this, because it really deserves its own whole episode, but traits can also define *associated items*. In the case of the `Iterator` trait, besides all its methods, the trait defines the existence of an `Item` type, which implementors have to define – an `Item` is the kind of thing an `Iterator` iterates over, and which the various methods handle and return. It’s not a struct field or anything like that; it’s *purely* a type-level detail. You can think of it as kind of being like a generic, except that these associated items can themselves be generic. And having them as these (quote-unquote) “associated items” means that we don’t have to specify the type of the generic for every place we call the trait method; we can just say at the place we implement `Iterator` that its `Item` is a `String`, or a `u32` or a `MyStruct`, and then whenever we call it it will *always* be that type, rather than needing its generic parameter specified. If that flew past you, don’t worry. As I said: we’ll spend a whole episode on associated types in the future: there’s a lot there! For now, it’s sufficient to know that you can require implementors of a trait to say “Hey, the things you’ll operate on in this method are these specific types.” That’s what associated types gives you! #### Trait inheritance As I suggested a few minutes ago, traits can also specify that they depend on other traits. So if you’re writing a trait that requires a type also implement `Iterator` – perhaps so you can `map` over it – you write that with your trait name, followed by a colon, followed by the “super-trait” name: ```rust,ignore trait AwesomeMappable : Iterator { awesome_map(&self) { // do something awesome } } ``` Anything which implements `AwesomeMappable` now also has to implement `Iterator`. This is handy both for extending the behavior of existing traits, and also for *relying* on the behavior of existing traits, as you define your own. ### Implementing other crates’ traits on your own types You can also implement other crates’ traits on your own types. So, thinking back to a recent Crates You Should Know episode, you often do just this with the `Serialize` and `Deserialize` traits from `Serde`. As you may recall, in that specific case, you *usually* implement those traits for your types using the custom derive macro: `#[derive(Serialize)]`. But of course you don’t have to: you can write the implementation yourself: `impl Serialize for MyStruct { ... }`. And this goes for *any* trait defined outside your crate and types you want to define inside your crate: `Iterator` is another common example, from the standard library. ### Implementing your own traits for other crates’ types Now, as I mentioned at the top of the show, one of the things that makes Rust’s traits fairly unique among programming languages in wide use is that you can implement a trait on a type that already exists. The only other examples *I’m* familiar with for doing this are *extension methods* in C♯, extensions in Objective-C and Swift, and type classes in Haskell. Perhaps the biggest difference with C♯ extension methods is that it’s actually extremely *common* to do this in Rust. You *can* do it in C♯, you almost certainly *will* do it in Rust. Let’s take our `Eatable` trait again, but let’s do something truly absurd and apply it to the regex crate’s `Regex` struct. “But Chris,” you say, “You can’t eat regular expressions.” To which I say: Rust gives us super powers! It even lets us eat regular expressions! We just have to write the `Eatable` implementation! ```rust,ignore impl Eatable for regex::Regex { fn prepare(&self) -> String { String::from("This is truly absurd.") } fn eat(&self) -> String { format!("{} But we can do it anyway!", self.prepare()) } } ``` Then we can take *any* instance of `Regex` in our crate and call `that_regex.eat()` and we’ll get back “This is truly absurd. But we can do it anyway!” And it is indeed absurd in this case. However, you can imagine many cases where this kind of thing would be handy: anywhere you want to be able to use the behavior you’ve defined on a struct defined outside your own crate. This is handy even just when using crates as strong API boundaries within your *own* codebase, but it’s also handy for dealing with types from *outside* your code. ### The orphan rule Now, there’s one thing you *cannot* do here: you cannot define an implementation of a trait from outside your crate for a type from outside your crate. The reason is simple: if *you* define an implementation for a trait from crate A for a type from crate B in your crate, and then I define a different implementation for the same trait from crate A on the same type from crate B that you did, and then someone uses both your crate and my crate… which implementation of the trait wins? Rust doesn’t have any good way to resolve it! The rule is: you can implement a trait for a type as long as *either* the trait *or* the type is local to your crate; you cannot implement external traits on external types. This is sometimes called the *orphan* rule – from the idea that one of the *parent types* (either the concrete type or the trait type) is missing – so hopefully you won’t be confused if you hear that in the future. ### Using trait methods One other thing that’s worth note here is a little detail that often trips up newcomers to the language: that when you want to use a *trait method* on a given item which implements that trait, you have to import the trait itself. So, for example, when you want to call a Serde serialization or deserialization method on a type which implements those, you *must* reference the appropriate Serde trait with a `use` keyword. The reason for this is that you need to tell Rust *which method* of that name to use. There’s no reason a given `struct` or `enum` cannot have multiple traits which define the same method name, and accordingly Rust needs a way to disambiguate between the options. Requiring the desired trait to be in scope is Rust’s normal way of solving this problem. You don’t *usually* import multiple traits that have the same method on them. (We’ll talk in a minute about how to solve it if you do.) So, for an easy-to-understand example: quite a few different traits out there in the world may define a `from_str`. And you might want implementations of more than one of them for any given type. You can imagine a `Printable` trait (somewhat analogous to the real `Display` trait in the standard library), and a `Convertable` trait that takes strings and turns them into an appropriate type (somewhat analogous to deserialization) – both of which define `from_str` definitions as appropriate to what they do. If you had a `struct MyThing` which had implementations of both, and both traits were in scope, how would Rust know which one you meant? This leads to the last detail we need to understand, which is how to *disambiguate manually*. After all, perhaps in some function you end up wanting to use *both* the `Printable` and the `Convertable` trait’s versions of the method. How can we do that? Here it’s worth remembering that a *method* is syntactical sugar for calling the function with the first argument explicitly. This is true for *all* methods, not just trait methods. (This will be familiar to listeners who’ve spent time working deeply with Python.) In this case, we can call the trait method we want to use directly: `Convertable::from_str("some string literal")`. There’s an example in the show notes showing this exactly with our `Eatable` trait and an even sillier trait called `Nomable`, as in “nom nom nom.” Your other option is to change the scope for importing a given trait. *Any* block is a possible location for a `use` statement. So you can import the traits you need to use which happen to have the same method name in different blocks – whether that’s different function bodies, or just standalone blocks within a function body –instead of at the top level of the module like you normally would. ## Closing And that particular detail does it for the *first* half of our deep dive on traits! In the next episode, we’ll dig deep on *trait objects*, including the `impl trait` and `dyn trait` features which are about to land on stable Rust! Thanks to this month’s $10-or-more sponsors: - Aaron Turon - Alexander Payne - Anthony Deschamps - Chris Palmer - Behnam Esfahbod - Dan Abrams - Daniel Collin - David W. Allen - Derek Buckley - Fábio Botelho - Hans Fjällemark - John Rudnick - Matt Rudder - Nathan Sculli - Nick Stevens - Peter Tillemans - Paul Naranja - Olaf Leidinger - Oluseyi Sonaiya - Ramon Buckland - Raph Levien - Vesa Khailavirta - and Zachary Snyder If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for _this_ episode at . If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e024-script.md ================================================ # e024: Traits Deep Dive, Part II ## Intro Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is episode 24: Traits Deep Dive, Part II. In the first part of this deep dive, we talked about the details of defining your own traits and what you can and cannot do in terms of implementing and using traits defined elsewhere. In this episode, we’re going to *start* talking about how you can use traits in place of concrete types. And in the *next* episode, we’ll expand on that to talk about the `impl trait` feature that just landed on stable Rust with 1.26! And yes, this was originally going to be a two-part deep dive, but as I got deep into this episode I realized that there was no way I could cover everything I needed to cover in the way I needed to cover it in a reasonable amount of time. Which makes sense: after all, traits are Rust’s primary mechanism for abstraction, and they’re *extremely* capable. So… three episodes it is! ## Syntax as sugar The first thing I want to cover today is how a number of bits of Rust syntax are actually *sugar* for traits. This is something I've mentioned before, but it’s worth digging into a little further. The most important of these are traits related to operators in Rust, like `Add` for addition, `Index` for indexing, `Iterator` for loops, and so on. It looks likely that something similar will be in play with async and await with `Future`s in the future. The way this works is that there are a set of traits the Rust compiler has special knowledge of. It's not that the traits get special privileges in terms of their capabilities with respect to the language. It's rather that some *syntax* in the language gets turned back into the same old normal traits that everything else is. Made more concrete: these traits are just traits like you could write; what's special-cased is the syntax. Rust *doesn't* let us invent new operators. It *does* express its existing operators largely in terms of the same kinds of things we *can* write: traits! So, to grab one of those earlier examples: when you write `a + b`, that's equivalent to calling `a.add(b)` or `b.add(a)` or even `Add::add(a, b)`. The *operator* is special syntactical sugar for the *trait*. This is certainly not unique to Rust, of course, and Rust is actually quite restrained compared to many other languages in terms of how much of this kind of thing you can do. C++ and Swift, for example, let you override *every* mathematical operator; Haskell lets you freely invent your own. There are upsides to those things, but the downside is that when you see a symbol it may mean something quite different than you expect, or you may have no idea what it means at all. Rust has chosen to go a different direction. First, there is a core set of operator traits, which can be implemented for new types, but you cannot create your own new operators. Second, because they’re *traits*, operators are subject to the “orphan rule” we talked about last time. As such, you can't reimplement traits for core types even if you're feeling clever. There was an [interesting discussion on the internals forum](https://internals.rust-lang.org/t/pre-pre-rfc-for-paths/2420/) a few years ago about whether to add support for using the `/` character as a path-join operator (as you can in Python). While a few people liked it, it definitely didn't fit the way Rust *normally* approaches these things, and so it was dropped. It's not so much a right-or-wrong kind of thing, as what fits with the rest of the language and what people expect. The upshot to all of this, in any case, is that you can `impl Add` for your own types and have the `+` operator just work. So, for example: let’s say that we have the example of a point in 3D space, with *x*, *y*, and *z* coordinates. ```rust,ignore use std::ops::Add; struct Point { x: i32, y: i32, z: i32, } impl Add for Point { fn add(self, other: Point) -> Point { Point { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z, } } } ``` Now we can add any two point instances together with the `+` operator. ## Using traits Now, let’s dig in further on the *use* of traits. The first things we’ll talk about have to do with *generics* and traits. Generics and traits relate in two ways: traits can be generic themselves, and traits can be used to constraint generic types. ### Generic traits Traits themselves can have generic types. They *don’t* usually, because instead you most often end up using *associated types*. As I’ve mentioned, I have an episode in the pipeline (probably a month or two out yet) to talk all about associated items. It’s worth noting, however, that you *can* write a generic trait. To return to our absurd example of the `Eatable` type from the previous traits deep dive episode, we could do this: ```rust,ignore trait Eatable { fn eat(&self) -> T; } impl Eatable for i32 { fn eat(&self) -> String { self.to_string() } } ``` Then anywhere we had an `i32`, we could call `.eat` on it and get back a string. We could also do `impl Eatable` with some *other* type in the generic position and get something totally different out. But this suggests why we generally prefer to use associated types: because we need to manually write down one of these generic implementations for every distinct value of the type parameter we have. More on that in a future episode *all* about associated items, including associated types! ### Traits in generic constraints and `where` clauses One of the primary places you’ll see existing traits is as *constraints* for generic types. This lets us write functions which are generic not over *everything* but over *anything which implements a given trait or set of traits*. For example: you might have a special function for displaying a given set of data—perhaps you want to render some HTML with the values in a struct, for example. In that case, you don’t really care what the concrete type is, you just care that it has the `Display` trait implemented. So you’d write your function as *generic* over any type which implements `Display`. There are two ways to write that. The first is with the trait constraint inline, right by the generic type parameter it constrains. ```rust,ignore fn render_html(displayable: T) -> HTML { // ... } ``` What we’re actually saying here in type terms is that our type `T` must be a *subtype* of `Display` – but other than that, it can be anything. Note that “subtype” here isn’t identical to the idea of a “subclass” in OO languages, even though “subtype” and “subclass” *are* often the same in those languages. In Rust (as in programming language theory more generally), a subtype is merely any type which is *substitutable* for another type. In traditional OO languages, one way you get at this is via the user of interfaces—no surprise then that we see it with traits in Rust. Now, back to our trait constraint example where we are marking some generic `T` as a subtype of `Display`. Besides writing it inline, we can write this with a *where clause*. Where clauses start with the keyword `where` and go immediately after the return value for a function. If we rewrote our `get_html` function with a where clause, it would read like this: ```rust,ignore fn render_html(displayable: T) -> HTML where T: Display { // ... } ``` This has the same *meaning* as inline constraints, but it becomes really important where the trait constraints on generic parameters gets to be long – *especially* the cases where you have multiple generic type parameters and each one of them has one or more trait constraints. When there *is* more than one trait constraining a generic, you separate them with a `+`. So here, for example, if our generic type `T` needed to be totally ordered as well as displayable – perhaps so we could sort them – then we would write the constraint as `T: Display + Ord`. This kind of constraint can be used for items in both argument and return position. A prime example of the way you can use it in return position is the `std::iterator::Iterator::collect` method. This one has some surprising properties when you’re not used to it (and, honestly, some surprising properties even when you *are* used to it)—so much so that I once saw someone [describe it](https://users.rust-lang.org/t/what-topics-would-you-like-to-see-covered-in-a-video-course-about-rust/10500/14) as *feeling* like overload-by-return-type. #### Explanation: monomorphization What’s actually happening is indeed something *kind of* like overloading in other languages. I’ve mentioned this before, but this is a good time to trace it out in a bit more detail. With Rust’s generics, the compiler does a process called *monomorphization*. Monomorphization is the process of taking something which is *polymorphic*—i.e. something which represents many forms—and turning it into something which has *just one form*. So, for a concrete, if rather trivial, example: ```rust,ignore use std::fmt::Display; fn to_string(t: T) -> String { format!("{}", t) } ``` (We wouldn’t ever really write this function, of course; we’d use the `std::string::ToString` trait for this instead. But it’ll do.) We have here a function which is generic over the type `T`, where `T` is constrained to “any type which implements `Display`.” It’s *polymorphic*: you can pass many different types—many different shapes!—into it. The only that matters is that those shapes have an implementation of `Display`. But for performance reasons, we don’t want to leave it polymorphic. We don’t want to have to do anything special at runtime for generic functions like looking them up in a table of versions to call, or putting things behind pointers and adding both indirection and allocations as a result. We just want functions we can call normally, as if we had written a concrete type here instead of a generic type! So when the Rust compiler gets to this in your program, what it actually does is go through and figure out all the different types which get used *as* this generic `T`, and then create a specific version of the function for each of them. For example, say you had called `to_string(42i32)` and `to_string(some_ipv6_address)` and `to_string(some_custom_type)` (where `some_custom_type` is one of your own types where you’ve implemented `Display`). Rust would then create three versions of the `to_string` function; under the hood they each get their own names, which including the crate and module name and a hash to disambiguate them. The “generic” function is gone entirely; it’s just those three individual normal functions. This is a prime example of Rust’s aim to have “zero-cost abstractions.” You don’t pay any more runtime cost for this than you would have by writing those individual implementation functions by hand (which is how you’d have to do it to avoid the aforementioned pointer and dynamic lookup costs otherwise). One other note on the compiler: with a function this simple, it’s likely that you actually wouldn’t end up with functions here at all: Rust would probably just inline it all. But the idea is what we’re interested in here. #### Monomorphization on return types That first, kind of silly example was dealing with monomorphization of *argument* types, but Rust does exactly the same thing with *return* types. So we can return to our motivation example of `std::iterator::Iterator::collect`. The signature for `collect` is: ```rust,ignore fn collect>(self) -> B where Self:Sized; ``` Let’s talk through this: `collect` is generic over a type `B`, which has the *constraint* that `B` must implement the trait `FromIterator`. `FromIterator` is a *generic trait*, as we discussed above. The generic parameter for `FromIterator` defines the type returned by its `from_iter` trait method, and the definition of `collect` says that the type returned there will be the `Item` associated time from the `Iterator` implementor on which `collect` is called. (It’s actually slightly more complicated than that; there’s an associated item and *another* trait involved, but I don’t want to get too far from `collect` for right now; you can look at the API docs for all the details.) So the function is *returning* a generic type `B` which implements `FromIterator` for the kind of `Item` contained in the iterator we’re dealing with. And the result is that `collect` can take your iterator and wrap it back up into almost anything as long as it has the pieces it needs. You can’t go from a simple list of values to a `HashMap`, for example, because you don’t have anything for the key type. But you also get the compiler telling you that, because `HashMap` doesn't implement `FromIterator` for an iterator over a simple list of values! On the other hand, you *can* go the other way: you can collect from an iterator over a hash map into a `Vec` instance, because it can just collect the values. ### Who’s in control? One important thing to notice here – and remember this, it’ll be important next time when we talk about `impl Trait` – is who’s in control of the type when we’re dealing with generic arguments or generic return types. When we have a generic *argument* type, we’re basically saying “for *any* type T which satisfies this trait constraint, I will do the right thing.” That means that the *caller* in control of the type: when I call some generic function with a concrete type, I as the caller have control over the type that goes in. When we have a generic *return* type, we’re basically saying “I will give you *some* type T which satisfies this trait constraint.” That means the *function itself* is in control of the type you get back. This starts taking us into some interesting type theory ground – specifically, into *universal* and *existential* types. We’ll talk a bit more about that next time in the `impl Trait` discussion. For now, just try to internalize the notion that for generics with trait bounds in argument position, the function will take *any* matching trait; for generics with trait bounds in return position, the function will return *some* matching trait. ## Closing So that’s a pretty thorough look at how we can use traits in conjunction with generics. In the next episode, we’ll finish up this deep dive on traits, taking a look at how we can use traits directly as arguments and return values, including the new `impl Trait` syntax from Rust 1.26. We’ll also dig into the extremely important concept of *object safety*. Thanks to everyone who sponsors the show! This month’s $10-or-more sponsors included: - Hans Fjällemark - Dan Abrams - Martin Heuschober - Chip - Nick Stevens - Nathan Sculli - John Rudnick - Zachary Snyder - Daniel Collin - Matt Rudder - Oluseyi Sonaiya - Peter Tillemans - Anthony Deschamps - Alexander Payne - Vesa Khailavirta - Chris Palmer - Ramon Buckland - Damien Stanton - Daniel Mason - Derek Buckley - David W. Allen - Behnam Esfahbod - Aaron Turon - Ryan Osial - Paul Naranja - Olaf Leidinger - Marshall Clyburn - Raph Levien If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for _this_ episode at . If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e025-script.md ================================================ # e025: Traits Deep Dive, Part III ## Sponsor: [Parity Technologies](https://paritytech.io) Hello, everyone! Over the last few years, I’ve had a number of opportunities for company sponsorships of the podcast; none of them were a good fit. Today, I have one that *is* – and it’s a *great* fit. [Parity Technologies](https://paritytech.io) is advancing the state of the art in decentralized technology. Their flagship software is the Parity Ethereum client, but they're also building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Their next big project is Polkadot, a platform leveraging blockchain tech for scaling and interop in decentralized systems. And Parity uses Rust for its trifecta of safety, speed, and correctness! And they’re hiring Rust developers! So if you’d like to work on any of these projects, check out their jobs at [paritytech.io/jobs](https://paritytech.io/jobs). Thanks to Parity for sponsoring the show! ## Intro Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is episode 24: Traits Deep Dive, Part III. In the first part of this deep dive series, we talked about how to write and implement traits. In the second part, we talked about using traits as bounds on generic types. In this third and hopefully final part, we’re going to look at using traits directly in argument and return position, including the new `impl Trait` syntax and the important concept of object safety. If that sounds like a lot to cover to you, it sounds like it to me too, so let’s jump in! First, though, a quick correction from the *last* traits deep dive episode: thoughtful commenters on both Reddit and Hacker News correctly pointed out that I was mistaken in my discussion of universal and existential types! I said that in the case of *generics with trait bounds*, arguments are always “universal” and return values are always “existential” – but this isn’t true with generics – the `Iterator::collect` method example I discussed on the show is a prime case where the caller is in control of and specifies a specific return type, after all! Thanks for that correction! ## Plain traits as arguments and return values There are several ways you’ve been able to use traits *without* generics since Rust 1.0. However, they have historically had some gotchas, many of which just got resolved with Rust 1.26 and 1.27, and one of which *will* be resolved in the future. So let’s dig in! ### Motivation I’ve spent quite a while thinking about how to explore this particular idea, and had gotten stuck repeatedly. Happily, a couple weeks ago while I was on vacation, a reader of my [Exploring 4 Languages](https://www.chriskrycho.com/exploring-four-languages.html) series had a question from the most recent post there, on [Starting to Model the Domain](https://www.chriskrycho.com/2018/exploring-4-languages-starting-to-model-the-domain.html). In that post, I noted that Rust lets us write out function types as type aliases if we want—though I noted that writing out type aliases for functions isn’t *usually* something we’d see. The reader who emailed me asked: > Could you give a small code example of how to use a function type alias like this Rust? It is very hard to find an example of this usage (probably because it is unconventional in Rust). And as it turns out, this is a perfect setup for the rest of this episode! One time when it’s convenient to write out an alias for a *function* – not just for “narrowing” a generic or something like that – is when you have some complex or nested transformation you want to apply to a data structure in the context of a [`std::iter::Iterator::map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map) invocation. You might want it to be testable, and you might want it to be passed into some other function for the sake of abstraction (maybe there are multiple valid kinds of transformations from input type to output type that you’re interested in). For example, let’s say we want to write a function which lets us get the distances of a set of points from some other point. Let’s assume some basic machinery: ```rust,ignore use std::{ f32, ops::Sub }; #[derive(Default)] struct Point { x: f32, y: f32, } impl<'p> Sub for &'p Point { type Output = Point; fn sub(self, other: &Point) -> Point { Point { x: self.x - other.x, y: self.y - other.y, } } } ``` Now, if we wanted to get the distances between one of those points and another, we could do that inline, using the Pythagorean theorem: ```rust,ignore fn main() { let a = Point { x: 1.0, y: 2.0 }; let b = Point { x: -4.5, y: 12.2 }; let change = a - b; let distance = (change.x.powi(2) + change.y.powi(2)).sqrt(); } ``` So far so good, but what if we had a *bunch* of these points – say, a `Vec` of them – and wanted to get their distance from some other point? Well, then it makes sense to iterate over them and use the `std::iter::Iterator::map` method. To do *that* we need a closure: ```rust,ignore fn main() { let points = vec![ Point { x: 1.0, y: 2.0 }, Point { x: 12.0, y: 4.3 }, Point { x: -5.4, y: 18.7 }, ]; let origin = Point::default(); let distances: Vec = points .iter() .map(|&point| { let change = point - origin; let distance = (change.x.powi(2) + change.y.powi(2)).sqrt(); }) .collect(); } ``` Now, what if we find this “get the distance between two points” function useful and wanted to extract it? Well, we could do that by extracting a function which takes two points by reference and returns the distance between them: ```rust,ignore fn distance_between(a: &Point, b: &Point) -> f32 { let change = a - b; (change.x.powi(2) + change.y.powi(2)).sqrt(); } ``` And this is *fine* – when we want to use it in the context we laid about above, we’d just have `|point| distance_between(&point, &origin)` in our `map` invocation. However, we could actually go one step further here and let ourselves create a function which we can “preload” with the desired comparison point: a function `distance_from` which takes a `Point` as its argument and returns a *function* which takes *another* `Point` as its argument and then returns the distance between the two. Then you could just write the invocation like this: ```rust,ignore let origin = Point::default(); let distances: Vec = points .iter() .map(distance_from(&origin)) .collect(); ``` That’s much clearer to read (at least to me). Unfortunately, though, writing out the signature for that function has been a pretty complicated thing, historically. For one thing, you had to wrap that up behind a heap allocated pointer, like: `Box f32>`, and it’s actually *really* hard to write this type and get the lifetimes all lining up correctly if you want to use references instead of moving all the `Point` instances: ```rust,ignore fn distance_from<'a, 'b: 'a>(offset: &'b Point) -> Box f32 + 'a> { Box::new(move |point| { let change = point - offset; (change.x.powi(2) + change.y.powi(2)).sqrt() }) } ``` Now, to get back to my reader’s question, it would be really nice, since `Fn` is a trait, if we could write a type alias for this! Something like: ```rust,ignore type DistanceFrom<'a> = Fn(&'a Point) -> f32; ``` Then we could use that in our definition: ```rust,ignore fn distance_from<'a, 'b: 'a>(offset: &'b Point) -> DistanceFrom<'a> { // ... } ``` Unfortunately, that specific definition isn’t quite valid – remember, we had a box around it before. So the correct definition using a `Box` would be to wrap that in a box at the call site: ```rust,ignore fn distance_from<'a, 'b: 'a>(offset: &'b Point) -> Box> { // ... } ``` Now that’s an improvement in a number of ways. But with Rust 1.26, we got `impl Trait`, so can’t we use *that* here? It would be really nice to write something like this: ```rust,ignore type DistanceFrom<'a> = Fn(&'a Point) -> f32; ``` and then use `impl Trait` with it: ```rust,ignore fn distance_from<'a, 'b: a>(offset: &'b Point) -> impl DistanceFrom<'a> { // ... } ``` Unfortunately, we can’t do this… yet. Type aliases can’t be used for traits types like this. However, I’m definitely not the first one to think it’d be useful to be able to write trait aliases! [RFC #1733: Trait aliases](https://github.com/rust-lang/rfcs/blob/master/text/1733-trait-alias.md) will give us just that. The syntax would be: ```rust,ignore trait DistanceFrom<'a> = Fn(&'a Point) -> f32 + 'a; ``` Someday! In the meantime, though, we can still use `impl Trait` – we just can’t use it with the nice convenient name. ### Traits in return position So… on to a topic we’ve been waiting for for quite a few episodes now. Why *would* we want to use `impl Trait` instead of a box here? Most obviously, it simplifies our (non-aliased) function signature and implementation a bit. Now it reads like this: ```rust,ignore fn distance_from<'a, 'b: 'a>(offset: &'b Point) -> impl Fn(&'a Point) -> f32 { move |point| { let change = point - offset; (change.x.powi(2) + change.y.powi(2)).sqrt() } } ``` The major change here is that the `Box` is gone – both in the signature and in the body of the function. Historically, we always had to return any *trait object* – that is, a piece of data where *all we care about* is that it implements a specific trait – behind a pointer. Why? Well, because that trait object could be pointing to all sorts of different sizes of things. A two-variant enum and a 40-field struct can implement the same trait – but the Rust compiler requires that every output from a function be the same size. The only candidate – at least historically – has been a heap-allocated pointer! A `Box` is always the same size. (A regular reference is, too, but then we’d need a lifetime to tie it to, and... there isn’t one available.) Whatever item we could define in the body of this function actually has to be *moved* out of it, or it’ll get dropped at the end of the function. So our only option here historically was a heap-allocated pointer. This had a couple important consequences: 1. We had to pay the price of that heap allocation. 2. More importantly, it also requires dynamic dispatch—looking up the specific function to execute at runtime instead of at compile time. One of the main reasons for the monomorphization we talked about earlier is to get *rid* of this runtime overhead. Those costs are small, and they’re often trivial—the kinds of things you don’t need to worry about. But they are *real* costs, and in the contexts where Rust is *most* useful, it does matter. So those were important limitations. ### Traits in bare argument position Many of those limitations also applied to the other place you might have been tempted to use a trait by itself, as the type of an argument. For example, you might think you could write ```rust,ignore fn foo(thing: SomeTrait) {} ``` But the same basic issue is at play as in the return type context. Rust needs an item with a constant size to be able to do this correctly. So we take a reference to the trait type; using a pointer means we have a type with a known size again: ```rust,ignore fn foo(thing: &SomeTrait) {} ``` We can also accept a heap-allocated pointer here, but in general we don’t actually *have* to: we can just write `&SomeTrait` and both regular references and also any type which implements the `Borrow` trait will work. (For a refresher on `Borrow` you can go back and listen to e018!) In any case, we have to put the trait type behind a reference, and as such we have dynamic dispatch with its small runtime cost – though in this case we do *not* (necessarily) have a heap-allocated pointer backing the trait object. This is extremely handy any time we don’t have a single specific type we’re going to be returning from or dealing with in a given function. For example: anywhere that we might be returning different specific iterator subtypes (`Map` and `Filter`, for example), or where we’re operating over a heterogeneous collection, where the only thing we care about in the collection is that every item in it implements some trait. ### `impl Trait` and `dyn Trait` We know enough now to see that at least in principle, the Rust compiler should often be able to figure out exactly what type we’re talking about when we want to return a trait type or take a trait type as an argument. After all, it already does exactly that with generics! And generic types with trait bounds notably do *not* require a heap allocation or dynamic dispatch. The compiler statically figures out the specific types they’re invoked with and return, and monomorphizes them—makes a version for each. So why can’t it do that for trait types too? As of Rust 1.26, it can. The new `impl Trait` feature lets us monomorphize the type here. From our perspective writing the code, the type of a closure – that we can’t name concretely, because it’s anonymous and Rust makes up a name at compile time – is just “something which implements the `Fn` trait with these argument and return types. But Rust compiles it down to the actual single function with that anonymous type. And now, it has a specific return type *size*, so we can get rid of the pointer. No more heap allocation, and no more runtime lookup cost. That goes for both argument position and return position. To return to my correction at the beginning of the episode: *this* is where universal and existential types come into play! (And I got mixed up with them because of how I split this episode into two parts.) `impl Trait` in argument position is a *universal* type, an “any” type specified by the caller; and `impl Trait` in return position is an *existential* type, a “some specific” type specific by the callee. The limitation of `impl Trait` is all those times we still need dynamic allocation and a heap allocated pointer. For those, we have another slight change landing for the Rust 2018 edition, which just reached stable Rust in 1.27: the `dyn Trait` syntax. Where before, we were allowed to simply write `Box` or `Rc` or even `&Trait`, now those invocations should be `Box` or `Rc` or `&dyn Trait`. The reason is to make *explicit* that there’s a trait object in play, not just a regular `struct` or `enum` type. That’s really important for making sure you have the right mental model in place – and, as I noted in my discussion of the feature in the recent Rust 1.27 news episode, it also makes for a nice symmetry between trait objects with `dyn Trait` and existential and universal types with `impl Trait`. ### Trait objects and object safety I’ve used the phrase “trait object” often throughout the episode – and for good reason; this idea is important. Any time we’re talking about dealing with some item *as a trait behind a pointer* rather than as a generic or concrete type, we’re talking about this idea of “trait objects.” Trait objects let us deal with heterogeneous types dynamically at runtime, but *safely*, much as interfaces do in tradition object oriented languages. But there is a very important set of rules which govern “trait objects” and allow us to use them safely in Rust, called “object safety.” This set of rules comes up any time you’re trying to use traits for this kind of abstraction in your programming; and since traits are Rust’s primary tool for abstraction, well… it’s going to come up pretty regularly. A few minutes ago, I noted that the compiler requires a constant size for return values from functions. The compiler captures this with `Sized`: a marker trait which tells the compiler that the item in question has a constant size known at compile time. (For a review on marker traits, you can go back and listen to episode 22, on the `Send` and `Sync` marker traits). This marker trait has two rules attached to it for object safety. 1. The trait itself *cannot* require that the special `Self` type be `Sized`. Instead, *trait methods* can set that requirement when needed—but only when needed!—with a `where` clause. 2. All of a trait’s methods must themselves be object safe. There are also two rules for object safety for trait methods: 1. They cannot have any type parameters, that is, they cannot be generic. 2. They must not use the `Self` type themselves. These rules come down to the reality that when you’re dealing with a trait object, Rust essentially “throws away” the concrete type or types you’re dealing with – as it has to, since it needs to treat every different concrete implementation behind the trait object the same way. But if you reference `Self`, Rust needs to be able to get back to the concrete type. These things are clearly at odds! So mostly, if you need a trait to be object safe, just avoid referencing `Self`. For further reading on object safety, I’ve linked a few important things in the show notes: - [RFC #255: Object Safety](https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md), which is the formal definition of object safety in the language - [Ch. 17 in the Second Edition of *The Rust Programming Language* ](https://doc.rust-lang.org/book/second-edition/ch17-02-trait-objects.html) - [A detailed explanation](https://huonw.github.io/blog/2015/05/where-self-meets-sized-revisiting-object-safety/ "Where Self Meets Sized: Revisiting Object Safety") of these ideas by Huon Wilson from around the Rust 1.0 release ## Closing That’s a wrap on our our deep dive on traits! The next main teaching episode will be a look at `unsafe` and the escape hatches it does and doesn’t allow. Also coming up are a look at functional programming ideas in Rust and a pair of Crates You Should Know episodes focused on Futures and Tokio! Thanks to everyone who sponsors the show! This month’s $10-or-more sponsors included: - Behnam Esfahbod - Anthony Deschamps - Chris Palmer - Ramon Buckland - Alexander Payne - Daniel Collin - Paul Naranja - John Rudnick - Marshall Clyburn - Martin Heuschober - Oluseyi Sonaiya - Hans Fjällemark - Vesa Khailavirta - Ryan Osial - Daniel Mason - Chip - Raph Levien - Derek Buckley - Damien Stanton - Aaron Turon - Nick Stevens - Peter Tillemans - Dan Abrams - Nathan Sculli - Zachary Snyder - Matt Rudder - Sascha Grunert - David W. Allen You can sponsor the show at , or send a one-off at any of a number of other services listed at the website. Even more importantly, please let others know about the show – by telling them about it at a meetup, sharing it around in whatever media you use, or reviewing or recommending it in your podcast directory of choice. You can find the notes for *this* episode at . The website also has scripts and code samples for most of the teaching episodes and transcripts for many of the interviews. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e026-script.md ================================================ # e026: Functional Programming Ideas in Rust Hello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust Programming Language and the people who use it. This is episode 26, functional programming ideas in Rust. ## Sponsor: Parity Technologies Before we jump in: Parity Technologies is back sponsoring the show again! Parity is advancing the state of the art in decentralized technology. Their flagship software is the Parity Ethereum client, but they're also building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Their next big project is Polkadot, a platform leveraging blockchain tech for scaling and interop in decentralized systems. Parity uses Rust for its trifecta of safety, speed, and correctness—and they’re hiring Rust developers! So if you’d like to work on any of these projects, check out their jobs at paritytech.io/jobs. Thanks to Parity for sponsoring the show! ## A little context I’ve been thinking about the relationship between Rust and functional programming essentially since the day I first *really* discovered the language, back in the summer of 2015. I was primed for Rust by reading Pat Brisbin’s little book Maybe Haskell, which uses the `Maybe` type in Haskell as a very basic introduction to functors and monads and applicatives. It blew my mind, because I had been looking for—and trying to implement in my own haphazard ways in the C and Fortran and Python codebases I was working in at the time—the ideas that `Maybe` represents. I did not come away from that little book totally grasping functors or applicatives or monads. In fact, my main takeaway was something more like: “Wait, you can get rid of `null` once and for all? You can handle it *in the type system*? YESSSSS.” When I bumped into Rust just a few months later, the fact that `Option` and `Result` existed, along with pattern-matching, sold me 100%. I needed no further convincing. Rust, as I’ve often put it, is basically what you would get if you mashed together C++ and Haskell. And that combination is interesting: it’s *not* exactly functional; but it’s not exactly the C++ style of imperative, object-oriented code, either. I’ve spent a lot of time talking over the last few years about how Rust is both like and unlike C++. Here, today, I thought it would be interesting to tease out some of the ways it’s similar to and dissimilar to functional programming languages. ## Functional Programming and Rust Let’s start with some of the ways Rust is *similar* to functional programming languages – or, perhaps a more accurate way to say it, some of the ways Rust steals ideas from functional programming languages. ### Similarities First, like most languages developed over the last few decades, Rust has a bunch of what you might call *functional-inspired idioms*. The entire `Iterator` API, for example, leans hard on ideas from functional programming: `map`, `fold`, and similar are probably the most common bits of cross-pollination from functional programming into imperative and object-oriented languages. You’ll find the same with C♯’s LINQ and Java’s Streams API, along with similar patterns in JavaScript, Python, Ruby, and so on. Rust borrows a bit more from functional programming languages than those other languages, though, in its type system and its approach to shared functionality. Whereas most of the other languages I just mentioned put classes front and center, and use classes as their primary mechanism for shared behavior, Rust *doesn’t*. As we talked about over the past three teaching episodes, Rust separates data definitions from the functionality which operates on the data; and it puts traits front and center for shared behavior. In this, it’s stealing directly from functional programming generally with the separation between data and behavior, and from Haskell specifically with its notion of type classes as a means of shared behavior. This is, I suspect, one part of what makes Rust so *odd*-seeming to many people who come to it from languages like C++ or Java or Ruby. It’s a particular delight to me, because I (like many others) have long found the separation of data from behavior to be a useful pattern. Rust just elevates that to a prime feature of the programming language. The last major way Rust steals from functional programming languages is in its type system. In particular, its `enum` types are bog-standard in functional programming languages. “Tagged unions” are certainly *possible* in procedural and object oriented languages—I built them or things like them myself in C, Python, and JavaScript—but they’re not first-class citizens of any mainstream imperative or OO language, and they don’t have the pattern-matching special sauce that makes them so powerful in Rust, OCaml, and so on. In fact, Rust’s `enum`s are probably my favorite of the things it borrows from FP languages, because I find them to be a particularly powerful and helpful way of expressing a lot of the kinds of problems I encounter. In short: Rust borrows a *lot* from functional programming languages. But not everything. ### Differences And what’s most interesting to me is that for all of those similarities, Rust*isn’t* in the end a functional programming language. It’s a language which, having stolen a ton of ideas from functional programming, turns around and adds its own spin on top of them. The major place this shows up is in Rust’s approach to mutability and imperative code—both of which it embraces, and that’s actually really important for getting the kinds of performance characteristics we get from Rust. #### Shared mutable state I’ve often heard it said by fans of functional programming languages that *shared mutable state is the root of all evil*. What people mean when they say this is that one of the major classes of bugs in our code is not logic errors, but simply shared state that multiple pieces of the code can write independent of each other. “Shared mutable state” makes it harder to track whether the invariants that are supposed to hold for a given piece of data *do* in fact hold. And functional programming is far from the only programming paradigm to recognize this. There is good reason that *global* mutable state is widely recognized to be a disastrously bad idea in *all* modern programming languages. And in fact, much of what we do in an object-oriented style is a matter of managing the scope of mutable state. We encapsulate it into objects and restrict access to it – when there are specific constraints that have to be upheld for a given data structure, we’ll often prevent *any* direct access to it in favor of methods which do perform a mutation, but which we can guarantee perform that mutation *safely*. For example, you can think of a class which wraps a custom queue implementation, where the queue is just implemented as a array with indices that track the first and last positions in it. The vector is mutable state, but we minimize how we *share* it: we don’t expose it for others to access, and we control how you can add items to the end and pop them off the front. Functional programming’s insight is that even this model often ends up causing us problems, not least because as a system grows it can be difficult to understand (and therefore to continue enforcing) those invariants. More, the very statefulness of those data structures can often lead us into places where we have *implicit ordering* – all the steps you have to do to get the data structure into a certain shape, usually in the form of a bunch of method calls which return `void` and, in good encapsulation form, give me no idea how the data structure underneath has changed. I know I’ve written plenty of code that involved an absurd amount of setup to test, and that’s a pretty big code smell. Functional programming usually solves this problem by dropping the mutability from the equation. It’s not a problem to have shared state if it isn’t mutable; everyone just has a read-only copy of the data and you create new copies of the data when you need it. Functions just take in data and hand back new data, without altering the original, even when they’re a transformation of the original. That probably sounds *super* expensive performance-wise, but we have smart tools for making that cost a lot less than it seems like it would; I’ll link to notes on persistent data structures if you’re unfamiliar with that idea! I’ll also link to a couple persistent data structure libraries in Rust, because this idea is useful here, too. I find this approach very powerful. It lets me *know* that if I have a given piece of data, it won’t be changed underneath me (no matter what function I pass it to!). It means testing is much simpler: just *create* the data I want to pass in directly, rather than making sure I do the right sequence of method invocations to hopefully get that shape right. All these things are great! They’re also expensive, though, performance-wise. Even using persistent data structures doesn’t get rid of that totally. Often, for application-level code, it doesn’t matter that much. But in some domains, at some times, it *does* matter. At the end of the day, mutation is *actually what happens* at the level of memory in a lot of cases, and abstracting over that has a cost, plain and simple. As such domains where pure functional programming isn’t 100% viable... tend to have an awful lot of overlap with Rust. #### Rust’s pitch: allow both, but never together Rust doesn’t give up on this insight about shared mutable state, though. It just takes a step back and says, “What if we allowed *both* shared state *and* mutable state but *never at the same time* and always make the relationship explicit?” In other words, it’s the same problem, but a slightly different solution. Rust, like functional programming languages, will *not* let us mutate shared state, because, well, all of the reasons we said above! But it *will* let us mutate *state that isn’t shared*. The entire point of Rust’s ownership rules and the borrow checker is to enable this additional way of solving the shared-mutable-state problem. I said a minute ago that it’s not a problem to have shared state if it isn’t mutable. But the flipside is also true: it’s not a problem to have mutable state if it isn’t shared. This might at first sound like we’re just back to encapsulation land, and that’s not *totally* wrong. Rust *does* let us keep internal data structures private, and we *do* lose some of those benefits of the total transparency from purely functional programming. However, the ownership rules go all the way down, you might say – and all the way up. In most higher-level languages, multiple objects can have references to a given data structure at the same time, and as such they can be calling methods on that data structure independently of each other, resulting in independent mutation of the underlying state. And because of the kinds of indirection in play, this can easily enough happen right under your nose: you call a method on one object, not realizing it updates another data structure “under the covers,” and then call another method on a different object, not realizing *it* does the same thing, and then go to look at the data and find yourself scratching your head at how the same value ended up in the target data structure twice. None of that is true in Rust! If a method is going to mutate inner state on the data structure it’s implemented for, it’s going to have to take self by mutable reference, and that means that whichever data structure or function is dealing with it has to have a mutable reference to it as well... and per Rust’s ownership rules, that has to be a *unique* mutable reference. We simply don’t have the problem where multiple different owners acted on a piece of data independently of each other, because no piece of data in Rust can have multiple owners. #### Ownership example To make this a little more concrete, let’s go back to our custom queue example from a few minutes ago. We might use a `VecDeque` under the hood, but intentionally not expose that in our `Queue` type publicly. In this case, the `Queue` would own the `VecDeque`. Its implementation would likely have `push` and `pop` methods, both of which would *have* to take self by mutable reference. That means that if you have two *other* data structures in your system which would like access to the queue, they cannot be in one of those states where one of them still has this mutable access to your `Queue` while the other doesn’t, and *this* means that you can’t have that weird thing where a side-effecting operation on one item in your system sneakily updated a data structure “behind your back.” The type system and ownership rules make it explicit who’s allowed to touch the `Queue`. You’d see right away – or at least, soon enough, when the compiler notified you! – that the intermediate data structures both tried to change the underlying data. And, perhaps most importantly, you’d generally have to do that by explicitly passing around the `Queue`, because you can *never* have two other data types which themselves both had mutable references to another piece of data at the same time, and you couldn’t even have two other data types where one of them had a reference *at all* while the other had a mutable reference. This doesn’t prevent you from making *logic* errors in this space, of course. You could intentionally get your lifetimes all in a row to make it so you could doubly-insert that data. But at a minimum, it would be much more obvious that was what you were doing! We’ve expanded the set of solutions to the “shared mutable state is the root of all evil” problem: we can write in a pure functional style (and that’s often quite useful in Rust!), but we can also take advantage of controlled mutability—emphasis on *controlled*! ## Closing I hope you found all of that helpful if you’re wondering about the relationship between Rust and functional programming! Certainly the way the two interact has been interesting to me over the past few years! Thanks to everyone who sponsors the show! This month’s $10-or-more sponsors included: - Behnam Esfahbod - David W. Allen - Derek Buckley - Matt Rudder - Chris Palmer - Vesa Khailavirta - Nick Stevens - Aaron Turon - Dan Abrams - Anthony Deschamps - Chip - Ryan Osial - Nathan Sculli - Daniel Mason - Martin Heuschober - Raph Levien - Peter Tillemans - Marshall Clyburn - Sascha Grunert - Alexander Payne - Paul Naranja - Rob Tsuk - Zachary Snyder - Daniel Collin - Hans Fjällemark - Oluseyi Sonaiya - Ramon Buckland - John Rudnick - Damien Stanton If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for \_this\_ episode at \. If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e027-script.md ================================================ # e027: I Promise; Trust Me Hello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust Programming Language and the people who use it. This is Episode 27: I Promise; Trust Me. ## Sponsor: Parity Technologies Parity Technologies is here sponsoring another episode! Parity is advancing the state of the art in decentralized technology. Their flagship software is the Parity Ethereum client, but they're also building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Their next big project is Polkadot, a platform leveraging blockchain tech for scaling and interop in decentralized systems. Parity uses Rust for its trifecta of safety, speed, and correctness—and they’re still hiring Rust developers! Check out their jobs at paritytech.io/jobs. Thanks again to Parity for sponsoring the show! ## What is safety? One of the most interesting claims Rust makes is that it can help us write *safer* code. I call this interesting because there’s a lot bundled up in that word: “safe”. We’re digging in, this episode, to the idea of safety through the lens of Rust’s keyword `unsafe`. But if we want to understand what we’re saying with `unsafe`, we need to understand what Rust means by “safe” in the rest of the code. Code marked `unsafe` is unsafe by *contrast* with the rest of Rust. So: what is safety? Safety is a specific set of guarantees about specific kinds of undesired behavior around memory. It is *not* a guarantee that your program will never crash, or that you won’t have logic bugs, or that you won’t get into deadlocks. It is a claim about *memory access* and *threads*, not about logic! The list of things Rust protects us from (and here I’m quoting from the Nomicon, the official Rust guide to writing `unsafe` Rust): > - Dereferencing null, dangling, or unaligned pointers > - Reading uninitialized memory > - Breaking the pointer aliasing rules > - Producing invalid primitive values: > - dangling/null references > - null `fn` pointers > - a `bool` that isn't 0 or 1 > - an undefined `enum` discriminant > - a `char` outside the ranges `[0x0, 0xD7FF]` and `[0xE000, 0x10FFFF]` > - A non-utf8 `str` > - Unwinding into another language > - Causing a data race That’s not a short list… but it’s not that long of a list, either! There are still plenty of things that can go wrong. For example: data races are prevented… but you can still have race conditions in a more general sense: those races just can’t cause memory unsafety. However, that list *does* eliminate a lot of the worst kinds of unsafety in the world of programming – and in particular, it eliminates the kinds of bugs that cause segmentation faults or corruption in the data of your program. This is what makes Rust such a big deal: those kinds of guarantees have only ever been available (in mainstream languages at least) in languages with managed memory. So safe Rust is pretty safe! ## `unsafe` So when we talk about “unsafe” Rust, does that mean all the rules go out the window? Happily, *no* We’ll dig into details around what it means to mark blocks, functions, or traits with the `unsafe` keyword in a minute. First, though, it’s important to understand that writing `unsafe` Rust does *not* mean you’re now in a free-for-all zone. If you’re *not* using one of the very specific additional abilities that `unsafe` unlocks, all of Rust’s other normal compiler rules and safety checking behaviors are still in play. You heard that right: the compiler checks you just as much inside an `unsafe` block as outside, other than some very specific abilities. So, for example, if you’re using a normal Rust reference instead of a raw pointer, the borrow checker will still check your access, just like normal! I’ve linked to [a Rust playground example](https://play.rust-lang.org/?version=beta&mode=release&edition=2018&gist=38d1089cdc3a4148609e9e3bbbfd002c) in the show notes so you can see exactly this (along with a warning that the `unsafe` block in the example is unnecessary). The takeaway here, before we dig into what each of those special `unsafe` abilities gains us, is that they don’t remove Rust’s normal safety checks in a general sense – they just let you do these specific *additional* (unsafe) things. As the Nomicon (the official Rust guide to `unsafe` Rust) [puts it](https://doc.rust-lang.org/nomicon/safe-unsafe-meaning.html): > The unsafe keyword has two uses: to declare the existence of contracts the compiler can't check, and to declare that a programmer has checked that these contracts have been upheld. One other thing to notice: just because we’re writing code in an `unsafe` block does *not* mean that what we’re doing is actually not a safe thing to do. In fact, the *point* is the opposite! We intend to write *safe* code in `unsafe` blocks. The difference is whether the compiler can know they’re safe or not. For this reason, people have suggested—with various degrees of seriousness, and none of them serious enough to write an RFC—that `unsafe` should have a different name: something like `vouchsafe` or `trustme`. Because code in an `unsafe` block is code where the normal trust paradigm with Rust is inverted: instead of *my* trusting the compiler to keep the code from ending up in conditions that would, say, segfault, the compiler has to trust *me* to keep the code from ending up in those conditions. So: what are the special abilities unlocked by the `unsafe` keyword? Just these ([quoting from](https://doc.rust-lang.org/book/second-edition/ch19-01-unsafe-rust.html) the most official source: The Rust Programming Language book): > - Dereference a raw pointer > - Call an unsafe function or method > - Access or modify a mutable static variable > - Implement an unsafe trait We’ll talk about each of those in turn. ### Dereferencing raw pointers The first thing you can do with `unsafe` is dereference a raw pointer. Let’s start by talking a little about the difference between a raw pointer and a normal “reference” in Rust, since “pointers” and “references” often get conflated in imprecise discussions. The difference between pointers and references is less one of *mechanics* and more one of *semantics*: what they mean and therefore what the compiler will let you do with them. Under the hood, both a raw pointer and a reference contain a memory address. However, semantically speaking, the *value* of a pointer is that memory address, while the *value* of a reference is the thing it’s pointing to. When you interact with a reference in Rust, you’re never concerned with the specific memory address involved: it is *only* a way of getting access to some item where it already exists, rather than having to copy all of its data around over and over. When you interact with a pointer in Rust, you are interacting with a specific `isize` value, which contains a memory location. It’s an `isize` because `isize` is the name of the type which is large enough to hold a memory address on the architecture you’re running on – so for a 32-bit architecture, `isize` is 4 bytes, and for a 64-bit architecture, it’s 8 bytes. If you somehow managed to get Rust running on an 8-bit architecture, it’d be 1 byte! But the point here is that the pointer is not just an indirection to get at some piece of data somewhere in memory: it is the address itself. That difference goes right down through the division between safe and unsafe Rust. Pointers and references are still pointers and references. And pointers are things you can do things with in safe Rust! You can get pointer values in safe Rust, e.g. with `Box::into_raw`. You can even mutate them, so that they point at something else, in safe Rust. (There’s an example in the show notes, as well as [a link to a Rust playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=3a7a9facd0f67d4a590afc3a3ecef95b) showing exactly this.) The huge thing you cannot do in safe Rust is dereference a raw pointer. That is: you cannot go “through” the pointer to get at the data at that memory location. In unsafe Rust, you can. The reason for this is simple: let’s say I get a pointer by calling `Box::into_raw` with a valid `Box`. That pointer is valid. But now, as I noted a second ago, I can change it. I could, say, just put the hex value `0x10` in it. And behind the address `0x10` is… who knows what? It could be uninitialized. It could be empty. It could be a different piece of data – maybe one being used by another thread! And when I call `Box::into_raw`, I get back a *mutable* pointer, so if I could dereference it, I could mess with the values on the other side of it. All of which means that I can create just about any kind of mess you can imagine if I’m allowed to dereference a raw pointer! Many of the data structure implementations in the standard library use `unsafe` heavily to do things that can be *verified* but are not doable with safe code. For example: the implementation of `Clone` for `Box` is `unsafe`, because it does a direct memory copy from one pointer location to another, and *that* is `unsafe` because the caller has to make sure that the source and destination locations (a) are both legitimate to access and (b) don’t overlap! ### Calling `unsafe` functions or methods So that covers raw pointers. What about `unsafe` functions and methods? The obvious reason we might need unsafe at the level of a function or a method is that the function cannot guarantee the safety of a given operation with just the information it needs to *execute*. That is: the function or method has guarantees *you* need to uphold – guarantees that should hopefully be very well-documented. A prime example of this is any kind of FFI interaction! If you’re dealing with memory from outside Rust – say, because you’re calling out to C, or because you’re using Rust to speed up an Elixir computation, or so on – by definition the compiler can’t check that you’re keeping things straight. It doesn’t know about everything going on in the other language! So calling a function that is in another language is inherently unsafe! ### Interacting with mutable `static` bindings Okay, now let’s talk about mutable `static` variables. `static`s are *global* items in Rust, and in safe Rust, they can’t be changed, because as a lot of people have said over the years, “Shared mutable state is the root of all evil” and mutable global variables are the definition of shared mutable state. A `static` variable in Rust has a specific, unchanging location in memory, and you can of course have references to `static` values in normal Rust. In fact, you *often* do: that’s what any static string is, for example! So if you could *change* them… you could have data races if multiple threads had references to that particular `static` at the same time and tried to read or write to it. Bad times would ensue. There are times when having a single piece of global, mutable state is useful, rare though they may be. But, as usual, we need to very carefully constrain how that is handled so we don’t shoot ourselves in the foot. Thus, we can only change *or* read mutable `static` variables in `unsafe` blocks. ### Implementing `unsafe` traits Note to readers: this section is incorrect; see the comments [in the show notes](/show_notes/e027/index.html#errata). Finally, we have `unsafe` traits. These are basically just one abstraction layer up from the things I just covered with `unsafe` functions and methods and with raw pointers. If a trait has a *method* which is `unsafe`, then the trait itself also has to be `unsafe`. The prime examples for `unsafe` traits are `Send` and `Sync`, which I covered back in episode 22. If you build a custom type that uses raw pointers, the Rust compiler by definition can’t tell if you’re using it in a way that is safe to share across threads (either as a value or a reference), so you have to write the `Send` and `Sync` implementations yourself… and that is unsafe, just as you would expect. ## Safe abstractions So those are the four things Rust lets us do with `unsafe`. But there’s more to say here, because the *most important thing* about `unsafe` in Rust is that you can constrain the unsafety. It isn’t a virus that infects everything it touches. You can (and basically always do!) wrap `unsafe` code with code that *is* safe. In fact, this is how large swaths of the Rust standard library are implemented. This ability to provide a safe abstraction around an unsafe implementation is at the core of what makes Rust viable. As we just talked about, there are things you *cannot* do in safe Rust code, but which you *have* to be able to do to get the kinds of performance we’re looking for. The trick is making it so that the other people using your code aren’t exposed to those unsafe things. This is of course not specific to Rust! Well-written C and C++ does the same kind of thing, and of course this same basic idea is fundamental to the notion of abstraction in programming. The difference with Rust as compared to C or C++ is that we have a tool for making the boundaries between the unsafe and the safe code explicit. Code inside an `unsafe` block is allowed to make those four moves we discussed, with all their ramifications. Code outside an `unsafe` block… isn’t. So when you write a chunk of `unsafe` code, you’re responsible to uphold the invariants required to make the safe wrapper, well, *safe*. Here’s an analogy. One of the fundamental data structures we use all the time is a stack, where the first thing in is the last thing out. From the perspective of someone using a stack, the only thing we care about is that we have the tools we need to put more items into the stack or to get items back out of the stack. However, there are lots of ways you can *implement* a stack while keeping those constraints for users. You could use a simple linked list. In Rust we could just have something like `Option>`, where the `Box` is our dynamic pointer to the next item. Every item in the stack would have `Some(Box)`, except the first one, which would have `None`. Or we could use a `Vec` and keep track of the latest item with an index pointing to the most recently inserted location in the vector. From the perspective of someone *using* the list, none of those details matter. We can choose the underlying data structure that gives us the best performance tradeoffs for our particular stack’s needs. However, we have to make sure that the functions we supply for interacting with our stack do what we say that they do! In the list-based variant, we need to make sure that we only ever append to the end of the list. Otherwise we’ll end up with a tree! (Happily, Rust would actually stop us here unless we switched from `Box` to something like `Rc`, because otherwise there would be two owning pointers.) Likewise, in the `Vec`-based version, we would need to be careful to set the index correctly when adding or removing items from the end of the `Vec`. We are responsible for upholding the invariants for our abstract data structure with the concrete implementations. This is exactly the same thing going on with `unsafe`. The abstraction around the unsafe code and the unsafe block itself are responsible to ensure that the function *does the right thing* with the data outside callers hand it. But now we’ve isolated it, at the programming language level, and we can know with confidence exactly where any bugs in the behavior of that unsafe abstraction come from. Or, to put a more positive spin on it, we can know where we need to focus our design and testing and verification efforts! I really liked how Nerijus Arlauskas put it in a blog post (which I have of course linked in the show notes), [Rust and OpenGL from Scratch](http://nercury.github.io/rust/opengl/tutorial/2018/02/08/opengl-in-rust-from-scratch-00-setup.html): > It may seem strange that “unsafe” exists at all. The reason for it is quite simple: it allows us to deal with complicated stuff once, inside a function with a safe API, and then completely forget about it when we become the users of that API. In other words, it moves the responsibility of correct API usage to API implementer. One last note here: in some languages, the default is that all items in a given module are public, and you have to go out of your way to hide them. That’s not the case in Rust – and it’s absolutely essential that it not be the case in Rust! We can (and indeed basically *must*) use privacy to make it so that we can uphold the invariants we need in a given context. Have a function you need that isn’t itself `unsafe` but which can break invariants that `unsafe` code needs upheld to make sure it works correctly? Leave it private to the module and write good comments explaining exactly how it has to be used to uphold those invariants: then the only possible places where things could go amiss are, again, scoped! ## Closing Thanks to everyone who sponsors the show! This month’s $10-or-more sponsors included: - James Hagans II - Paul Naranja - Ryan Osial - Chip - Bryce Johnston - Dan Abrams - Alexander Payne - Bryan Stitt - Ramon Buckland - Jako Danar - Nathan Sculli - Scott Moeller - John Rudnick - Steffen Loan Sunde - Matt Rudder - Raph Levien - Michael Mc Donnell - Chris Palmer - Oluseyi Sonaiya - Daniel Collin - Joseph Marhee - Brian McCallister - Nick Gideo - Graham Wihlidal - Nicolas Pochet - Behnam Esfahbod - Jonathan Knapp - Nick Stevens - Jerome Froelick - Rob Tsuk - Daniel Mason - Adam Green - Anthony Deschamps - Peter Tillemans - Martin Heuschober If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for \_this\_ episode at \. If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy (maybe unsafe!) coding! ================================================ FILE: docs/e028-script.md ================================================ # Meet My Associates Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is Episode 28: Meet My Associates. ## Sponsor: First up, I'm really happy to have Manning back sponsoring the show this episode! They're here with a discount on some *video content* they’ve put together. Even better because that video content is by Carol Nichols || Goulding and Jake Goulding—we talked about this content just a few episodes back! I’ve been saying for years that we need more video content: it’s a huge way people learn. Manning’s Rust in Motion is one of the first major video courses for Rust I know of. You can get it for 40% off at [deals.manning.com/new-rustacean](http://bit.ly/2OXnlEb) – there’s a link in the show notes. That link actually gives you 40% off of *anything* at Manning, including their book *Rust in Action*, which is in early access preview. Thanks so much to Manning for sponsoring the show and building some great video content with Carol and Jake! ## Associated Items Okay, so let’s jump in and talk about *associated items*. You can think of this as effectively being Traits Deep Dive, Part IV, because associated items are one of the last pieces of the story around Rust’s trait system that we haven’t covered. We’ve actually already talked a *lot* about a number of things which go under the label of “associated items”, because “associated items” actually covers basically *all* trait items! However, there are some nuances to that summary which are worth digging into, and there are some important kinds of associated items which we haven’t talked about *at all* yet on the show. Associated items are—and here I’m quoting the Reference— > the items declared in traits or defined in implementations. They are called this because they are defined on an associate type — the type in the implementation. They are a subset of the kinds of items you can declare in a module. Specifically, there are associated functions (including methods), associated types, and associated constants. We should notice here that associated items are a limited set of all kinds of items in Rust. You cannot define just *anything* on a trait. Most notably, you cannot in general define *type members* on a trait. That is: you could define a `trait Nameable` that has a method on it like `get_name(&self) -> String`, but you can’t include a property on it like `name: String`. That distinction is quite important, and it’s one of the ways Rust’s trait system is quite *unlike* most interface types in other languages. It’s possible to imagine a system where Rust's traits *did* define data, but that would end up undercutting one of the most important elements of Rust's core design: the essential distinction between data and behavior. Traits are behavior: that’s why you *implement* a trait for a data type with an `impl` block, just the same way you implement the behavior of the data type itself. So with that little clarifying note out of the way, let's look at all the things we *can* define on traits: associated functions, constants, and types. ### Associated functions We’ve talked about functions and methods before, during [Episode 23: Traits Deep Dive, Part I][e023]. There are just two things I want to highlight in this context: [e023]: https://newrustacean.com/show_notes/e023/ First, trait functions and methods are indeed a kind of associated type, because they’re a *type* that is associated with the thing implementing the trait! Simple as that. Second, and more importantly, when I talked about these back in episode 24, I skipped over the difference between associated functions and associated methods. Both are functions defined on a trait; the difference is whether the function takes `self` as a parameter in some way. If the function *does* take `self` as a parameter—whether it takes it by reference, moves it, or even takes it as `Box`—it is a trait method. If it does *not* take `self` in any way, it is just an associated function. Remember that the general syntax for calling a function attached to a type—whether that type is a struct, an enum, or a trait—is simply `TheType::some_function(with, any, args)`. And methods are just special cases of functions which take `self` as their first parameter. These rules work out exactly the same way for *associated functions*—functions defined on traits—as they do on concrete types. Notice, then, that methods (which I focused on in my previous discussion) are simply a special case of associated functions in general: they're just associated functions which take `self` as their first parameter. (And this is true of functions vs. methods in general in Rust! You can `impl` a function which doesn't take `self` on *any* type.) For functions which are *not* methods, and which are located on a type, you have to call them with the name of the type, a pair of colons, and then the arguments: `TheType::some_function(args)`. And since trait methods are just a special case of associated functions, you *can* call them the same way! But, as with all methods in Rust, you can also call them like `some_instance.some_method(args)`. And that's basically all we need to add about associated functions—most of it, I covered back in [the first Traits deep dive episode][e023], so check those out if you need a refresher. ### Associated constants Next up: associated consts. As I noted a minute ago, you cannot generally define members on a trait. There is one kind of member you can define on a trait, though: *constants*. A trait cannot have any *dynamic* members, but constants are allowed. Those of you who listened to my news episodes for Rust 1.31 and the 2018 Edition may recall that one of the features stabilized with 1.31 were `const fn` types useful for compile time programming. Well, associated constants—designed with the rest of the associated items system all the way back in [RFC #195], and stabilized back in [Rust 1.20]—are another of the tools available for that kind of work. [RFC #195]: https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md [Rust 1.20]: https://newrustacean.com/show_notes/news/rust_1_20/ There aren't a *ton* of places where associated constants come up, but they're quite handy when you have a known value associated with given trait that makes more sense with the *trait* than with its containing *module*. Numerics are one of the go-to examples for the obvious reason that there are lots of kinds of numeric constants that we care about, so if you were designing a library for fast numeric computation, you'd presumably want a lot of those values hard-coded as constants—but as constants on *types*, not just free-floating in a module. So you might have something like `Float::PI`, for example, where `Float` is the trait representing floating point numbers, and `PI` is the value 3.1415926… and so on, to whatever appropriate level of precision. To define this in the trait, you simply write a `const` type declaration, just as you would *outside* a trait – except that, just like with an associated function, you only have to *define* the constant, not *declare it with a value*. So for our `Float` example, in the body of the trait declaration, we'd simply have `const PI: f32`. I actually ran into a place where this was useful recently: I was building a small tool and needed to define some string types with different maximum lengths. I could have implemented this distinctly on each and every one of those types, but it was easier and clearer to write a new trait called `ConstrainedString`, which had two associated constants: `MIN_LEN` and `MAX_LEN`. Then I could build around it a default implementation for creating a new instance of the type with an associated function *given* those constraints. (There’s an example in the show notes, of course.) Just as associated functions and methods may or may not have default *implementations*, associated constants may or may not have default *values*. In the case of my example a minute ago, `Float::PI`, you would presumably want this to have a predefined value—it would be really odd and indeed *wrong* for pi to have different values for different implementations! But in the case of my `ConstrainedString` type, I did *not* want to pre-specify the constant values: the whole point is that those differ for each instance of the type. Instead, I define only the types the minimum and maximum lengths (`Option`) and then allow the implementor for the trait to specify their actual values! One other thing worth saying: associated consts are an example of a const context – a place where the compiler will perform constant evaluation including on const function types, as I covered in some detail in the second of my two episodes on Rust 1.31 and the 2018 Edition! ### Associated Types Okay, so much for the easy bits. Now let's talk about associated *types*. This is where things get a lot more interesting – both in the sense of increased power and also, as you'd expect, in the sense of increased complexity! In fact, associated *types* are one of the things that took me the longest to wrap my head around with Rust. (That’s one of the reasons it has taken me more than three years to get to them—along with everything *else* I’ve had to cover, of course.) Let's start with how you *write* an associated type. It turns out it's exactly as you would expect, given what you already know! Just as you simply write a `fn` signature (with or without a body) or a `const` definition (with or without a value) in the body of a trait definition to define a function or a constant respectively, you write a type annotation just like you would write a standalone type alias declaration: `type AssociatedThing;`. The canonical standard library example you've used over and over again (though quite possibly without knowing it!) is `std::iter::Iterator`'s associated `Item` type. Check out [the source][iterator-src] if you like—it's just: [iterator-src]: https://doc.rust-lang.org/1.32.0/src/core/iter/iterator.rs.html&version=1.32.0 ```rs pub trait Iterator { type Item; // and then the various associated functions } ``` "Just," I say, but this is one of Rust's most powerful features for keeping traits for exploding into a mess of generics upon generics. If you have an iterator that is generic, you can create an `impl` for an enormous number of different concrete types. So, reaching back to the ridiculous example I was using in the first two traits deep dive episodes, `Eatable`: if `Eatable` was a *generic* type, it might look like: ```rust trait Eatable { fn eat(&self) -> B; } ``` Then we could: ```rust # trait Eatable { # fn eat(&self) -> B; # } impl Eatable for i32 { fn eat(&self) -> String { if *self < 0 { format!("{} is gross", self) } else if *self < 10 { format!("{} is just fine", self) } else { format!("{} is delicious!", self) } } } ``` But we could *also* ```rust # trait Eatable { # fn eat(&self) -> B; # } impl Eatable for i32 { fn eat(&self) -> f64 { f64::from(*self) } } ``` Which, besides being a lot less interesting, shows us where the problem here is: if we actually try to use this, say by writing: ```rust,ignore let a = 13; a.eat(); ``` …well, now we have a problem. The compiler is going to tell us "multiple applicable items in scope -- multiple `eat` found" and then (as of Rust 1.32) the nice suggestion, "help: to disambiguate the method call, write `GenericEatable::eat(a)` instead". But if we try *that*, we get another error: "type annotations needed -- cannot infer type for `B`". The only way we can actually make it resolve is by writing `GenericEatable::eat(a)`. EWWWWW. This is gross! Now, gross or not it is *occasionally* necessary… but the truth is that most of the time we don't want arbitrary and unbounded genericism for our traits like this. Leaving aside the fact that we can't eat an integer in the first place (I mean, unless you decided to make an integer-shaped birthday cake, which I would be fine with), we usually want a *single* implementation of a given trait for a given type: eating an `i32` should give us a *string* describing how tasty it is, not an `f64` or some random struct. In other words, we want the ability to specify *one* other type here when we implement a trait for some specific type. An example of this rom the ecosystem which I think should help clarify why this is so helpful is Serde's `Visitor` trait. Serde uses `Visitor` implementations for defining how to walk through a deserializer structure – *visiting* each of the items in the data being deserialized. `Visitor` has a single associated type, `Value`: the type of thing produced by a given implementation. You `impl Visitor` for specific types you want to support custom deserialization for. If `Visitor` were a *generic* trait, then you'd end up with no way to say "always produce a type that's actually appropriate for using with `ValidatedEmail` type – but that's what you want. You don't want `visit_str` to produce a different output type when Serde is trying to deserialize into a `ValidatedEmail` than `visit_string` or `visit_borrowed_string` do. But with a generic, that would be quite possible. What you want instead is to have a single implementation of `Visitor` for `ValidatedEmail`, where the `Value` produced by that visitor is always a `String` – but with a *deserialization error* if it is not a valid email. And that's the beauty of associated types: when you implement a trait for a given type, it will only have exactly as many associated types as the *trait* defines. Two associated types on the trait, two concrete types for an implementation of the trait for some other type – vs. generics, where the number of generics is *multiplicative*: two generic types for a trait means *every* implementation for a type adds two more. ## Things to come There are also two features in this general bucket which I'm *not* going to cover, but which fit into this story and you should know about; I expect to cover them in a news episode as appropriate when they're stabilized. The first is *associated lifetimes*. These were defined in [RFC #195] with the other associated items, but (at least so far as I can see) were never implemented, and in fact [the Reference currently says][associated lifetimes] "Only functions, constants, and type aliases can be associated." The point here, per the RFC, would be to provide the same kind of constrained generic programming ergonomics for lifetimes as associated types provide for types. (This makes sense: lifetimes and types are both parts of Rust's *type system*, and they're closely related. That's why they both go in the same rough places syntactically in the language!) [associated lifetimes]: https://doc.rust-lang.org/reference/glossary.html#associated-item The idea of associated lifetimes leads us directly into the other thing, which I *do* expect to land sometime in 2019 or 2020: *generic associated types*, sometimes labeled with the initializism GATs, from [RFC #1598], where the feature was originally called "associated type constructors." I am not going to dig *especially* deep on this today, as I expect I will cover it in considerable detail when it eventually stabilizes. The gist is that an important limitation of today’s associated types will be lifted: they will be allowed to be generic themselves. Let’s flip that around: today, an associated type cannot be a *generic* type. So… why would we want it to be? After all, we just discussed a minute ago how the whole point of associated types is to avoid the problem that comes from the explosion of types with generics. Here I’ll use an example from the original RFC here: let’s say you wanted to write a trait that handled both the `Rc` and the `Arc` reference counted types, a “family” of types as it were. (For those of you with lots of type theory, yes, this is a *step* toward one way of capturing higher-kindedness, by extending Rust’s existing type system. For those of you without arcane type theory knowledge, don’t worry about it!) Ideally, you’d like to be able to have a `PointerFamily` trait with an associated type, `Pointer`, which you could then fill in for `Arc` or `Rc`… but `Arc` and `Rc` are `Arc` and `Rc`, so you can’t do that. We need to be able to say `type Pointer = Arc`, which means we need to be able to write the trait as something like `type Pointer: Deref`. The same kind of thing goes for lifetimes, which are their own kind of generics. So, some time hopefully this year, that will land (and I’ll give it an appropriate deep dive when it does). [RFC #1598]: https://github.com/rust-lang/rfcs/blob/master/text/1598-generic_associated_types.md ## Outro And that does it for associated items! Hopefully you have a better feel for associated *types* in particular; I know digging into them this way was quite helpful for me. Thanks as always to this month’s $10-or-more sponsors: - Alexander Payne - Andrew Dirksen - Anthony Deschamps - beaorn - Behnam Esfahbod - Brian McCallister - Bryan Stitt - Chip - Chris Palmer - Dan Abrams - Daniel Collin - Daniel Mason - Embark Studios - Graham Wihlidal - Jako Danar - James Hagans II - Jerome Froelich - Johan Andersson - John Rudnick - Jonathan Knapp - Joseph Marhee - Martin Heuschober - Matt Rudder - Michael Mc Donnell - Nathan Sculli - Nick Gideo - Nick Stevens - Nicolas Pochet - Oluseyi Sonaiya - Paul Naranja - Peter Tillemans - Ramon Buckland - Raph Levien - Rob Tsuk - Ryan Osial - Scott Moeller You can sponsor the show at patreon.com/newrustacean or via other services listed on the show website, . There, you’ll also find show notes, including links to things I talk about, scripts, code samples, and interview transcripts. The notes for *this* episode are at . Please recommend the show to others if you like it, whether in person, via your podcast directory, or in various media online! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending men an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e029-script.md ================================================ # e029: I’m Out To C Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is e029: I’m Out To C. ## Sponsor: Manning Manning is back sponsoring the show this episode! Once again they have a discount on some Rust *video content* they’re producing with Carol Nichols || Goulding and Jake Goulding, Rust In Motion—the very same we talked about when I interviewed them back in 2018! I’ve been saying for years that we need more video content: it’s a huge way people learn. Manning’s Rust in Motion is one of the first major video *courses* for Rust I know of (though I’m happy to report other video content is starting to appear as well). You can get it for 40% off at [deals.manning.com/new-rustacean](http://bit.ly/2OXnlEb) – there’s a link in the show notes. That link actually gives you 40% off of *anything* at Manning, including their book *Rust in Action*, which is in early access preview. Thanks so much to Manning for sponsoring the show and building some great video content with Carol and Jake! ## C FFI Now, let’s talk about Rust’s foreign function interface, or FFI, and specifically its *C* foreign function interface. For further materials on all of this, you’ll want to take a look at [The Rust Programming Language’s materials][TRPL], the [API] and the [Reference’s][reference] writeups on `extern`, and the [nomicon] section on FFI. And speaking of Jake Goulding, his [Rust FFI Omnibus] a nice complement to those! I’ve linked them all in the show notes! [TRPL]: https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code [API]: https://doc.rust-lang.org/1.33.0/std/keyword.extern.html [reference]: https://doc.rust-lang.org/1.33.0/reference/items/external-blocks.html [nomicon]: https://doc.rust-lang.org/beta/nomicon/ffi.html [Rust FFI Omnibus]: http://jakegoulding.com/rust-ffi-omnibus/ One of the key selling points for Rust is that you don’t have to just *replace* your existing code in other languages, including in C or C++, but can interoperate freely with them via C APIs—since nearly all modern languages have a C foreign function interface, or FFI. I’m actually going to talk a fair bit about that in the *next* teaching episode, both for extending other languages with Rust and for Rust calling into other languages. For today, though, we’re looking specifically at C and C++, because the interop for those other languages builds on what we have here. By definition, C has a C API. And C++ libraries *often* have C APIs or can be *expressed* as C APIs given a certain amount of finagling. But interacting with a C API means you have to write a bunch of Rust *bindings* for that API. A binding is a description to the Rust compiler of what the API looks like: a set of declarations of the types of both data structures and functions. It’s important that we get these right, because if we don’t, stuff *will* explode on us. Throughout the rest of this episode, I’m going to teach you a *tiny* bit of C, because in order to work with Rust’s FFI tooling, you’re going to need to understand at least a *little* bit of C. To do it really *well* when starting from scratch for interop with other languages, you’ll need to understand more, but in many cases there are tools already that mean you don’t have to do *all* the work yourself, which helps a lot. I’ll say more on that in an upcoming Crates You Should Know! ### `extern` The first thing we need to talk about is Rust’s `extern` keyword, which lets you define an external item: blocks, functions, types, and crates. I’ve linked to [the Reference’s writeup on `extern`][extern-reference], and it’s worth reading carefully. You may recall that `extern` in the Rust 2015 Edition was required to declare all crates outside the current crate, with the `extern crate` syntax. This told the Rust compiler “Hey, this name isn’t part of this crate; you’ll need to look it up somewhere else!” Rust no longer needs that for *crates* in the 2018 Edition, as I covered in the news episodes where I talked about “path clarity.” However, we do still need the `extern` keyword, because there *are* functions and types we need to tell Rust to look up “outside”: no surprise given today’s topic, those are for FFI! There are two forms where we use FFI. The first, which we’ll focus on in *this* episode, is `extern` *blocks*, which you use when calling out into something with a C ABI from Rust. The second is the `extern` modifier on an item declaration; we’ll talk about that in the *next* teaching episode, when we cover how you can use Rust from other languages. In either of those positions, the `extern` keyword may optionally be followed by an ABI definition. An ABI is an application binary interface. Just as an API—an application programming interface—tells you as a programmer how to connect *your* code with *other* code, an ABI defines for the compiler how to connect different binaries together. Put another way: as an API is to source code, an ABI is to machine code. Some examples of the kinds of things an ABI has to define: - how do data structures get laid out in memory? - how are functions named when compiled? - what is the processor instruction set to be used? - how do system calls work in this particular context? - how is the stack laid out? There are more details than that; the point is that those machine-level details are super important and you have to define them somehow. Rust has its own ABI, of course, though it’s not something you ever have to worry about unless you’re working on the compiler itself. What’s more, Rust’s ABI can and does change. Other, “stable” ABIs exist, though, which *don’t* change over time, and that is useful when you need to interact with code that compiles down to that format. You specify which ABI you want to compile against with a string literal after `extern`., e.g. to use the `stdcall` ABI on Windows, you’d write The most common one is the C ABI! There are two special cases to know about with `extern`: 1. When you write `fn foo()` (or indeed *any* item declaration), that’s equivalent to writing `extern "Rust" fn foo()`, specifying that this function will have the Rust ABI calling convention. 2. Because C FFI is far and away the most common, `extern` is short for `extern "C"`, both in blocks and in function declarations. An `extern` block is exactly what it sounds like: a block which is marked with `extern` (and optionally an ABI string). The two big takeaways here are: - *All* functions defined in an `extern` block are inherently `unsafe`, so even though you don’t have to and in fact *can’t* write `unsafe` on those declarations. - For *all* FFI, you have to wrap the definitions in an `extern` block. So, speaking of definitions… let’s dive in and talk about how you actually define `extern` functions and interact with them! ### The Basics Any time we’re interoperating with something via a C API, we’re dealing with *functions*: there’s no other reason or way to interact across this kind of boundary! We’ll start with a basic, apparently trivial example: calling out to C to perform addition. The C function signature is: ```c int add(int a, int b); ``` The body does what you expect: returns `a + b`. On the Rust side, we need to provide a *declaration* (but of course no definition) so we know how to call that function. We do that with an `extern` block and a function type with no body—somewhat like a trait method definition. ```rust use std::os::raw::c_int; extern { fn add(a: c_int, b: c_int) -> c_int; } ``` Notice the types here: `c_int`, *not* `i32`. Now, `c_int` is nearly always an `i32`, but it’s not *guaranteed* to be anything of the sort, so we use these types instead. The types are defined in two places: `std::os::raw` and the `libc` crate. The definitions are the same; the only reason I know of to prefer getting them from `libc` is if you’re in an environment without `std`, e.g. on an embedded system. Using `c_int` will make it so that if you happen to be on a system where it’s *not* an `i32` and you call it with an `i32` without an explicit cast, you’ll get an error. Handy! ### Building C libraries with `build.rs` Now, to make this work, you have to build the C you actually want to call. To do this, you’ll need to either use a tool outside of Cargo like Make, or use Cargo’s “build file” tool. For today, we’re just going to use the latter. In many cases, you’ll be using projects which already have their own build system, and will need to do some more work to tell rustc how to link those items into your app or library. The various references I mentioned at the top of the show all have info on how to do that. For our purposes, I’m going to use this as an opportunity to talk through Cargo build files! If you define a `build` key pointing to a Rust file in your `package` config in the `Cargo.toml` file, Cargo will compile and execute that Rust program before building the rest of your program. Conventionally, you can simply supply a file named `build.rs` and Cargo will do the same thing automatically, without even needing to specify the `build` key. If your build process is sufficiently complicated, you can just set up a `build` directory, make the root `build/main.rs`, and have a full Rust program in that directory which your `build` key points to. It’s quite powerful! You can also specify `[build_dependencies]`, which will only be used by the `build.rs` file. In the show notes for this episode, you’ll find a sample `build.rs` file which is using the `cc` crate to build a small bit of C code and set it up in the right spot to be statically linked into our program. The `cc` crate does the hard work of abstracting over the differences between C compilation environments on different platforms, so you don’t have to worry about working out those different invocations for `gcc` and `clang` and `msvc` and so on. ### Structs So that’s the *basics* for our `add` function, though I’ll have more to say about it in a moment. Let’s say we had a very traditional `struct` type in C, just a plain old record—we’ll go with a `Point` because that’s such a common example. Let’s also imagine we wanted the ability to *translate* the point, to change the coordinates from one location to another. In C, we’d write that like this: ```c typedef struct Point { float x; float y; } Point; void translate(Point * point, float byX, float byY) { point->x += byX; point->y += byY; } ``` Writing `Point* point` means `translate` requires a *pointer* to a given `Point` piece of data (but it makes no guarantees that there’s actually a `Point` behind it, only that C will treat the data layout as consistent with a `Point`). The net of this declaration is that we are taking in a *pointer* to a `Point` and can freely do whatever we want to the memory behind that pointer—quite *unlike* in safe Rust. We could also here mutate the pointer itself, pointing it to some *other* point in memory. If we wanted to make it so you couldn’t change what the pointer pointed to, we’d write it `Point *const point`. If we wanted to make it so we couldn’t change the *contents* of the point but could change what it pointed to, we’d write `const Point * point`. If we wanted to make it so we couldn’t change *either*, we’d write `const Point *const point`. Unfortunately, C would *also* let us cast away all of that attempted safety and just do whatever we wanted. In this case, we do the right thing: we just update the values in the `point`. Now we need to write those same definitions in Rust. First, the `Point` type. This looks pretty much like what you’d expect: ```rust use std::os::raw::c_float; #[repr(C)] pub struct Point { pub x: c_float, pub y: c_float, } ``` It’s *almost* just a normal `struct` type—`pub struct Point` with public properties `x` and `y`, both of type `c_float`. So far so normal. However, we also need to add an attribute, `#[repr(C)]`, to the struct declaration. This makes it so that Rust lays it out using the C ABI’s definition of how structs are laid out, rather than how Rust chooses to lay them out. Once we’ve added that, though, this definition is exactly the same as the C one and we’re good to go with interop. Next up, the function definition, but with raw pointers instead of references. I skipped over this in my discussion of `unsafe` code in Rust, because I knew we’d hit it in *this* episode: Rust has a similar notation, in the form of *raw pointers*, written `*const` and `*mut`. In Rust we’d write this same first argument `point: *mut Point`, since we’re passing a pointer pointing at a thing which will be mutated. Notice an important difference here: when we write `*const` in C, it means “you can’t change the pointer”; in Rust it means “you can’t change the thing the pointer points to.” The full function signature for this in Rust, then, is: ```rust use std::os::raw::c_float; #[repr(C)] pub struct Point { pub x: c_float, pub y: c_float, } extern "C" { pub fn translate(point: *mut Point, by_x: c_float, by_y: c_float); } ``` The other arguments here are straightforward: `c_float` for the same reason we used `c_int` in the addition example. ### Safe wrappers You *can* expose an unsafe interface that just provides direct interop with C functions in your code. However, this means that *everything* which uses that code has to uphold its invariants! As I discussed back in Episode 27, the Rustic way of doing things is to wrap our `unsafe` functions in safe Rust functions, which check that all the invariants are correctly upheld. That way the *vast* majority of your code—even your code that relies heavily on external C API code—can just be normal safe Rust; we *isolate* the un-safety and the complexity and the testing burden. So, taking that approach with the examples I gave above, we might have the same `extern` definition for the C functions, but wrap them in a non-exposed module—maybe called `ffi`—and only expose our own safe wrappers. That would be something like this: ```rust,ignore use std::os::raw::c_float; #[repr(C)] pub struct Point { pub x: c_float, pub y: c_float, } mod ffi { use super::Point; use std::os::raw::{c_float, c_int}; extern "C" { pub fn add(a: c_int, b: c_int) -> c_int; pub fn translate(point: *mut Point, by_x: c_float, by_y: c_float); } } pub fn add(a: i32, b: i32) -> Option { if i32::max_value() - a >= b { unsafe { Some(ffi::add(a, b)) } } else { None } } pub fn translate(point: &mut Point, by_x: f32, by_y: f32) { unsafe { ffi::translate(point as *mut Point, by_x as c_float, by_y as c_float); } } ``` The `add` definition here tries to do something *somewhat* reasonable when dealing with the possibility of overflow—not a *great* solution (and not even a *complete* solution, since you could underflow, too!), but we need *something* here. The reason is that as silly as this kind of check might seem—about as calling out to C for addition is!—even something like addition which might seem to be trivially safe… isn’t. While it might seem that something like addition is trivially safe, it turns out to be *mostly* safe. The behavior of overflow for signed integers is*not defined* for C. In Rust, it *is* defined, by [RFC #0560][RFC-0560]: in modes where `debug_assertions` are enabled, an overflow will cause a panic; in modes where those assertions are not enabled (i.e. release mode), Rust wraps them by [two's complement][tc]. The net of that is that even something this simple can have unexpected results when calling across the FFI boundary. [RFC-0560]: https://rust-lang.github.io/rfcs/0560-integer-overflow.html [tc]: https://en.wikipedia.org/wiki/Two%27s_complement This is a silly example, of course, but it shows how you can provide a safe wrapper for a case where C's implementation differences *might* actually matter to you… and it also serves as a reminder that C’s implementation differences are likely to matter in more places than you might initially think. In the case of the safe wrapper for `translate`, we don’t need to do anything except call `unsafe { translate(...); }`, because we don’t have any particular constraints we have to uphold other than that we legitimately have a non-null pointer to pass in—and pointers are *always* non-null when coming from safe Rust. But by wrapping it up this way, we’ve still made it so our consumers don’t have to deal with the un-safety. Here, I’ve chosen to add the explicit casts as a way of communicating to anyone reading the code what I’m doing, but none of the arguments actually *requires* it. Finally, it’s worth clarifying that our careful use of safe Rust interfaces does *not* mean something can’t go wrong here through our use of unsafe code. The C code itself could still do something horrible—cast the pointer to `void *`, point it at other junk memory, or even call `free` on it. Lots of things can go wrong in C (or indeed in other languages with C APIs) that Rust by definition doesn’t have control over. When we provide a safe interface like this, we are not saying anything at all about the actual behavior of the C API we’re calling into. The *only* thing we’re doing is saying that we’re providing data that satisfies the invariants the C API requires. ## Conclusion Okay, so that takes us through the basics of C FFI in Rust. There’s a lot more to say, though! In the next teaching episode, we’ll cover dealing with enums, types like strings and vectors and arrays and slices, ownership issues, and union types. After *that*, we’ll dive into talking about how you can use Rust *from* other programming languages! Along the way, there will also be a Crates You Should Know about bindgen. Thanks as always to *everyone* who sponsors the show. This month’s $10-or-more sponsors included: - Anthony Deschamps - Ryan Osial - Ola Fadeyi - Soren Bramer Schmidt - Rob Tsuk - John Rudnick - Chip - Brian McCallister - Jerome Froelich - Andrew Dirksen - Nick Stevens - Daniel Mason - Daniel Collin - Joseph Schrag - Jako Danar - Embark Studios - Peter Tillemans - Jonathan Knapp - Adam Green - Michael Mc Donnell - Matt Rudder - Graham Wihlidal - Benjamin Manns - Jeff May - Martin Heuschober - Oluseyi Sonaiya - Scott Moeller - Nathan Sculli - Behnam Esfahbod - Evan Stoll - Arun Kulshreshtha - Raph Levien - Ramon Buckland - Nick Gideo - Daniel Bornkessel - James Hagans II - Dan Abrams - Paul Naranja - David Carroll - Bryan Stitt - Nicolas Pochet - Johan Andersson - Jason Bowen - Alexander Payne - Zach Peters You can sponsor the show at patreon.com/newrustacean or via other services listed on the show website, . There, you’ll also find show notes, including links to things I talk about, scripts, code samples, and interview transcripts. The notes for *this* episode are at . Please recommend the show to others if you like it, whether in person, via your podcast directory, or in various media online! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending men an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e030-script.md ================================================ # e030: Can You See Me Now? Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is e030: Can You See Me Now? ## Sponsor: Manning Press Manning is back sponsoring the show this episode! This time around they have a discount on some Rust-adjacent materials—about one of my favorite things Rust excels at: WebAssembly. Manning has a book in their Early Access Preview period, WebAssembly in Action, which takes a deep dive into the language itself. This is *not* Rust-specific content: what it is instead is content that would be super helpful if you want to contribute actively to the development of Rust’s support for WebAssembly, or just want a deeper dive into wasm than I gave in my own episode on the subject. I’ve linked it in the show notes, and don’t forget that you can use the code `newrustacean40` at checkout to get 40% off on *anything* at Manning—including this WebAssembly book, all their Rust materials, and everything else they sell! Thanks so much to Manning for sponsoring the show once again! ## Visibility This is not the next episode I originally had planned—that one is coming in the next week or so. In the midst of working on e029, I started to put together a discussion of the idea of *visibility* in Rust, and then cut it for time. However, I realized it’s an important feature of the language that I’ve never covered, and it’s worth incorporating into its own episode. So: what *is* visibility, and why do we care? Visibility is the answer to the question: who can see this item? An “item”, here, is: - a module, - a function, - a trait, - an enum, - a struct, - a struct *field*, - or a (non-trait) method As for why we care: it turns out that having control over who can see any given item can be a really important factor in our API design. Things we expose publicly become part of our versioning story, and good and careful use of semantic versioning is a way we serve our library consumers. When Rust first hit 1.0, it only had two levels of visibility: `pub` and not `pub`. In 2016, with [RFC #1422], however, Rust got a bunch of new tools for controlling item visibility, and I think it’s worth understanding both how those tools work and how we can use them effectively. [RFC #1422]: https://github.com/rust-lang/rfcs/blob/master/text/1422-pub-restricted.md ### The modifiers There are 3 top-level kinds of visibility: - the default, of *not*-public, which means the item is visible only within its own module and its child modules; - `pub`, meaning the item is fully visible to all consumers of the crate who can see the path to the item; - and `pub()`, where the item is visible to some *restricted* range. There are also 3 variants of `restricted`: - `crate`, written `pub(crate)`, which means the item is visible everywhere in the crate but is *not* visible outside the crate - `super`, written `pub(super)`, which means what you’d expect: the item is visible to the parent module but nowhere else - `in `, written like `pub(in module_a::module_b)` where `module_b` is a submodule of `module_a`. Note that the `path` here can only include direct parents of the module where the restrict is written. The first two are the two that were always there. The `restricted` variants are what landed in 2016, and they’re mostly what makes this conversation interesting! I’m going to talk through these and how we can use them effectively, but you should also take a look at the show notes [source], where I’ve included a very detailed sample showing how all the different visibility markers interact. [source]: https://newrustacean.com/src/show_notes/e030.rs.html ### Traditional `pub` Now, let’s start talking about plain `pub` for a minute, because understanding `pub` clearly will help us make sure we understand `pub()` better—I actually had to read [the relevant section of the reference][reference] and play with things a bit myself to get 100% clear here! [reference]: https://doc.rust-lang.org/reference/visibility-and-privacy.html As I said a minute ago, `pub` on an item means that item is fully visible to all consumers of the crate who can see the path to the item. That distinction is really important, though! It’s not that putting `pub` an item makes it visible regardless of other modifiers. It’s that it makes it visible *given the constraints of other relevant visibility modifiers*. Let’s imagine we have a crate which has two modules in the root; we’ll call them `left` and `right`. If both of those are `pub`, they’re visible both to each other and to other crates which reference this crate. If `left` has a child named `public_child` which has the `pub` modifier on it, then `left::public_child` is *also* visible everywhere in the crate and to all outside consumers. If `left` has a child named `private_child` which does not have any modifier at all, it is *not* visible outside `left` at all. Now, if `left` had a sub-module named `child`, then items inside `left::child` could still see `private_child`: child modules can always see the items in their parent modules. Sibling modules do *not* have that characteristic, though. From inside our `right` module, we can see `left::public_child` because both `left` and `public_child` are marked as `pub`—but we can’t see anything inside `left` that *isn’t* marked as `pub`. We could work around this by restructuring our crate… but that really isn’t optimal, especially if you structure your modules around data types the way I talked about back in [episode 20][e020]. [src]: https://newrustacean.com/src/show_notes/e030.rs.html [e020]: https://newrustacean.com/show_notes/e020/ This limitation isn’t necessarily a *huge* deal for designing a binary application. However, it’s *really* annoying for library design. We want to be able to design our public APIs carefully, so that we only expose to consumers the things they can actually depend on… in part so that we can evolve the internals of our libraries while maintaining those external invariants. Having to make breaking changes all the time *or* come up with workaround hacks for where we put our internal-only-but-shared-throughout-the-codebase kinds of types and functions is a *not-great* tradeoff. This is where the `pub()` tooling comes in! ### `pub()` The `pub()` family of specifiers lets us get *much* more granular about the level of visibility any given item has, and this is extremely* helpful in solving the kinds of problems I highlighted a second ago. The most common modifier you’re going to see, I expect, is `pub(crate)`, because it’s the most *convenient*: it lets you say “This item is visible *everywhere* that has a path to it… but only inside *this* crate.” This is like `pub` in terms of convenience, in other words, but not in terms of its impact on your public API—because things which are marked as `pub(crate)` are *not* visible outside your crate! At this point, `pub(crate)` is basically my default visibility for items I want to expose. Sometimes I go back later and tweak that, but I find it’s often a perfectly reasonable balance between convenience and exposure. The *most* restrictive `pub` modifier is `pub(super)`. This is convenient for when you have a type which you’ve extracted to its own module for name-spacing purposes, in line with the recommendation I gave back in e020, and you want it to be freely available for its parent to use but you don’t really want it exposed to the rest of the crate you’re working on. You might be tempted, given `pub(super)`, to think you could just chain your way up with pairs of double-colons all the way to root of a crate: `pub(super::super::super::super...)`. After all, that is a valid way to write a path! However, that’s not a valid way of specifying visibility. `pub(super)` is just there as a shortcut for that one, very specific but fairly common situation of wanting to be visible in your parent module but not otherwise. Instead, if you want to write a restriction like that, you use the `pub(in )` form. So if you had the module path `foo::bar::baz` and wanted to make an item `quux` visible anywhere in `foo`, you could write that one of two ways: - `pub(in super::super)` - or, much more clearly, `pub(in foo)` You can write `pub(in ...)` with any path that contains the module the item is in. However, if some module somewhere in that tree is itself not visible the rest of the way up that tree, your item will only be visible up to that point. So if we wrote `pub(in foo) fn quux() {}` here but the declaration of the `baz` module inside `bar` was itself not any kind of `pub`, `foo` couldn’t see `quux`. This gets at one of two really important points about these visibility modifiers: they specify the *maximum* visibility an item can have—but other modifiers (or the lack thereof) can and sometimes will limit that. You may have to adjust accordingly. The other important thing to note here is that outer modules cannot override the visibility rules of their descendants. So with that last example, where we had the module structure `foo::bar::baz` and a function `quux` inside `baz` which is marked `pub(in foo)`, `foo` *cannot* write `pub use bar::baz::quux` to make it publicly visible everywhere. The restriction at the point of definition sets the visibility restriction universally. That’s the flip side of the same thing I said before: a visibility modifier is the *maximum* visibility of an item. ### Using visibility effectively The last thing to cover here, then, is how to use these most effectively. I covered some of this above, and I covered some related pieces back in e020, but I want to take a few here and talk through how *I* think about visibility modifiers and how you can use them as a tool both for external *and* internal consumers of your code. First and most obvious is the point I’ve already made a couple times in this episode: `pub` items are exposed to your external API consumers. Whether those are internal to projects at your company, or to the broader open source software ecosystem, those are a kind of *contract*. When you change what’s public, that’s a version bump—a minor release, if you expose something new; or a major release, if you remove or change something which was already public. That responsibility with versioning is one reason you should always think carefully about what you mark `pub`, and how you expose it. Another, and equally important, though, is that your API is a way of communicating to your users. You really can help people understand and navigate their way through your code just by the shape of your API! The way that items are exposed and the way they’re grouped and namespaced in modules shouldn’t be arbitrary, but rather a way of helping your users think the right way about your codebase. You’ve probably had the experience of looking at a library which just had a grab-bag of functions and types in it with no structure: it’s a mess and takes a long time to understand! But you’ve probably also had the experience of working through the APIs for a really carefully-designed library and thinking, “I wonder if… yeah, perfect, that’s right where I thought it would be!” or even “Oh, of course, that makes sense!” when you stumble into some new corner of it. Care in what you make `pub` and *where* you make it `pub` from is really valuable—so much so that you may want to use `pub use` statements to take items which are indeed public throughout your crate and re-export them in strategic locations, whether for convenience or just because it makes for a clearer sense of how different pieces relate to each other from the perspective of a *user* rather than an *author* of a library. All of those points about communication hold for internal visibility, too. It’s just that you have a different audience in mind: your *users*, in this case, are *other developers*. When someone starts working their way through the codebase, it can be incredibly helpful and illuminating to see `pub(crate)` or `pub(in some:nested::modules`) as the visibility modifier for a given item. First of all, those can tell you the number of places you might have to care about when dealing with a given type. If you’re looking at a crate with 50,000 lines of code, and you see `pub(crate)`, you know that a refactor *could* end up touching thousands of lines of code. And while the Rust compiler will guide you through that, there are still important signals there: this item is probably deeply entangled with the current semantics of the system I’m looking at. That means that changes to that item are, for one thing, likely to have large ripples through the rest of the system and, for another, likely to have ended up in the shape they did for a reason. Those are useful signals in understanding a codebase! And by the same token, if you see `pub(super)` on an item, you can be 100% confident that it’s *not* going to be used in very many places. It might still have an equally well-considered design, but changes to it are going to cause many fewer ripples and have a much smaller impact on the design of the rest of the system. Again: that’s really useful information to have! The same way that thinking about what is `pub`, and where it is `pub`, is useful for your *external* users, `pub()` is helpful for your *internal* users. Finally, there’s one other thing you’re communicating with by way of visibility modifiers, and that’s the compiler. You can use these as a way of constraining yourself. The same way that we isolate unsafe code in `unsafe` blocks inside safe interfaces which maintain all the right invariants, we can use visibility modifiers to isolate certain kinds of complexity—data structures, algorithms, etc.—which are important for the rest of our codebase not to muck with. If a given piece of code needs to uphold a certain contract in order to maintain its *performance* characteristics, for example, you can manage with visibility modifiers just the same way you would use safe wrappers around `unsafe` to maintain *safety* characteristics. The way you should think about visibility markers, then, is that they’re *communication tools* and *tools for enforcing invariants*. That combo means, as I’ve realized in the course of writing this episode, that while my default of using `pub(crate)` for convenience is fine on small projects, thinking a bit harder about which kind of modifier to use might get me a long way—especially when dealing with a larger project or one with more complex edge cases than I’ve gotten myself into so far. ## Outro I hope you *also* found this discussion useful, both in understanding how other codebases are structured, and in considering how you might structure your own codebase—especially how to use visibility as a tool for providing a nice experience both for maintainers of your code (including yourself!) and, if you’re a library author, for *consumers* of your code. ### Patreon Sponsors Thanks as always to this month’s $10-or-more sponsors: - Arun Kulshreshtha - Matt Rudder - Soren Bramer Schmidt - Dan Abrams - Oluseyi Sonaiya - Anthony Deschamps - Evan Stoll - Nick Gideo - Dominic Cooney - Embark Studios - Scott Moeller - Benjamin Manns - Daniel Mason - Jonathan Knapp - Nick Stevens - Jeff May - Behnam Esfahbod - Johan Andersson - Nathan Sculli - James Hagans II - John Rudnick - Zach Peters - Chip - Jerome Froelich - Andrew Dirksen - Joseph Schrag - Brian McCallister - Bryan Stitt - Raph Levien - Nicolas Pochet - Daniel Bornkessel (April only) - Ryan Osial - Jason Bowen - Jako Danar - Michael Mc Donnell - Adam Green - Alexander Payne - Rob Tsuk - David Carroll - Ramon Buckland - Martin Heuschober - Peter Tillemans - Paul Naranja - Graham Wihlidal - Ola Fadeyi - Cristian Paul - Daniel Collin ### Show info You can sponsor the show at patreon.com/newrustacean or via other services listed on the show website, . There, you’ll also find show notes, including links to things I talk about, scripts, code samples, and interview transcripts. The notes for *this* episode are at . Please recommend the show to others if you like it, whether in person, via your podcast directory, or in various media online! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending men an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/e031-script.md ================================================ # e031: FFI Deep Dive! ## Intro Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is e031: FFI Deep Dive! ## Sponsor: Parity Before we dive in, Parity is back sponsoring the show—because they want to hire you to come work in Rust with them! Parity is advancing the state of the art in decentralized technology, and they’re using Rust to do it, leaning hard on its trifecta of performance, reliability, and productivity. They're building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Two of the larger projects they're working on are: Substrate, a framework for building blockchains, and Polkadot, a platform leveraging blockchain tech for scaling and interoperability in decentralized systems. If that sounds interesting, check out their jobs at ! ## Colorado Gold Rust One quick bit of news from the community: the Colorado Gold Rust call for proposals is open, so if talking to and hanging out with a bunch of Rustaceans (almost certainly including me!) in Colorado this fall sounds like fun, please submit a proposal. ## Rust for FFI Okay, now, let’s dig in. A couple episodes ago I talked about doing C FFI from Rust. Today, we’re going to flip that around and see how you can use Rust for FFI from *other* languages. Languages *plural* because everything I cover here is equally relevant to using Rust as the FFI layer for, say, Elixir or Python as it is for integrating Rust into an existing C or C++ codebase. And in that respect, this is actually *more* interesting than just calling with a C API from Rust: because it lets Rust provide safe super-powers for other languages! There are two basic kinds of things we need to cover today: - exposing Rust functions and data types *to* other programs via the `extern` mechanics we talked about last time - and handling richer data types both *from* other languages in Rust, still using those `extern` mechanics but also adding in the idea of *opaque types* Throughout all of this, I’m very indebted to Jake Goulding’s FFI Omnibus. ### Making Rust functions available to other programs The first of these is essentially the inverse of what we talked about in e029. In that case, we were defining Rust signatures for types or functions that are coming in from other languages—specifically, from C APIs. How do we go the other direction, though? Let’s say we were working in a language like Elixir, or Ruby, or JavaScript, or Python, and had some hot loop that we needed to go *much* faster? Because Rust can exposes a C foreign function interface, you can use Rust instead of C for native extensions to those languages! We’re going to work through this in three parts: numbers, strings, and other more complicated types. For anything more complicated than a number, we’ll talk about what you have to do to be memory-safe as well. Finally, we’ll wrap up the episode by talking about opaque pointers: a very important tool for safe interop! You should, once again, definitely take a look at the sample code in [the repository for the show][repo]: I’ve made the show notes work as a library which you can dynamically link against from anything expecting a C ABI. In particular, you’ll want to look at the code in the `e031` directory, which includes a `mod.rs` and associated `e031.c` and `e031.h` files, and at the `build.rs` file in the root, which includes a *very* simple setup for building those C files into an executable you can run, showing that this stuff actually works. To try it, check out the code and run `cargo build`; you’ll get a binary file in the root of the crate called `link-against-rust` and you can run it to see that it does what I claim it does! Unfortunately, that only works on Unix-like operating systems because I don’t have a good way (or the time!) to set this up on Windows—but you should be able to make it work on the genuinely great and constantly-improving Windows Subsystem for Linux. [repo]: https://github.com/chriskrycho/newrustacean ### Configuring a project First, let’s talk through how you actually expose *anything* for *consumers* of a Rust-based C-style API. To make a function available over Rust’s C FFI, we have to do just a couple things: 1. We need to update our crate definition a bit. By default, Rust library crates are build as `"lib"` crates, which means they’re *Rust*-compatible, but they could be any of a number of formats; the compiler gets to decide which. However, `"lib"` crates are *not* C-compatible. So in our crate definition, in the `[lib]` section, we write `crate-type = ["cdylib"]` (assuming you’re on at least Rust 1.10; before that you had to use just `"dylib"`). This crates a dynamically linked library artifact which is designed to be linked into a C program. If you run `cargo build` after doing this, you’ll see a dynamically-linkable library file for your OS: `.so` on Linux, `.dylib` on macOS, `.dll` on Windows. You may have noticed that I said to write a TOML *array* for the `crate-type` value. That’s because you can actually pass *multiple* values in there. So if you want to build a library for consumption *either* as a dynamically-linked library for C consumers *or* for static linking into a Rust program… you can do that! You just write `crate-type = ["lib", "cdylib"]`. Then if you do `cargo build` and look in `target/debug`, you’ll see both an `.rlib` file and the appropriate dynamically-linkable library file for you platform. 2. As with last time, we’re going to use the `std::os::raw` or `libc` libraries to make sure we’re writing types that do what we need them to, rather than Rust’s own native types. In general, `libc::` is just another name for `std::os::raw::`. Remember: the big difference between the two is that libc doesn’t require std, so if you’re working in a context where you need to build in `no_std` mode—embedded environments, for example. 3. Mark each function we want to make accessible to non-Rust callers with the `#[no_mangle]` attribute. This tells the Rust compiler *not* to do the normal name-mashing it does, where it takes all the information about a given function—including its module, generic monomorphization, etc.—and turns that into a distinct name for each way the function can be invoked. If you pull down the source code for the show and do a `cargo build`, you can actually inspect the output for the `cdylib` it now creates using the `objdump` or `nm` tools, which let you look at the symbols in a given binary file. You’ll notice a bunch of names that look *sort of* like names from the Rust standard library… but mangled! You’ll also notice a couple functions whose names *aren’t* mangled if you search down through: `add_in_rust` and so on. These are the functions you can see in the show notes for this episode, which are exported publicly with the `pub` and `extern` modifiers and marked with the `#[no_mangle]` attribute. That’s it for the basic *mechanics*. ### Numbers Now, we can start seeing what it looks like to put this into practice, with some simple numeric examples. Happily, numbers are pretty easy. In fact, for numeric work, it’s safer and easier extending other languages with Rust than reaching out to C APIs *from* Rust, because in this case, Rust is in control of everything—importantly, including things like overflow. We’re not doing unsafe things here! (That’ll be a bit different when we talk about more complicated types in a minute, but… we’ll get there in a minute.) I’ve put in the show notes a super simple example of this: addition. We just write: ```rust use std::os::raw::c_int; #[no_mangle] pub extern "C" fn add_in_rust(a: c_int, b: c_int) -> c_int { a + b } ``` There shouldn’t be anything surprising about that if you listened to e029. We’re using the `c_int` types to make sure we’re using the types of the sizes C consumers expect—whether those C consumers C, C++, Elixir, JavaScript, or whatever else. We make it `pub` so that external consumers of the crate can see it. We mark it `extern "C"` so that it’s guaranteed to have the right ABI, as we talked about in e029. We mark it with `#[no_mangle]` so that the name ends up in the format expected for linking in as a C-compatible library. And, for this simple case… that’s it on the Rust side! On the consuming side, you’ll also need to *declare* that with a C declaration: ```c extern int add_in_rust(int a, int b); ``` Otherwise your C library or binary simply won’t compile because it won’t know that something outside itself is supposed to be supplying that symbol. It’s marked `extern` as well, but in the C case that means the function has external linkage and storage duration. The details of that aren’t really relevant for us, but they *are* worth understanding if you’re doing a bunch of this. These kinds of numeric calculations are a prime place where Rust can be a super helpful way of speeding up a scripting language. If you have some large, computationally-intensive task you need to do, that’s reasonably isolated from other code, and your profiling shows you that there’s a hotspot there, writing a native Rust extension to do that work can often be a perfect solution. Of course, in many cases, you’re dealing with something like an array of data—so we’ll need to figure out how to pass that kind of thing across the FFI boundary! ### Strings We’ll start with one of the most common vector-based data structures: strings! There are two ways we need to be able to deal with strings: when *Rust* owns them and is handing them off to a C API, and when *the C API* owns them and Rust is dealing with them. For this we’re going to use what seems like a pretty simple example: concatenating two strings. As anyone who has worked with strings at a low level knows, though, doing this *correctly* and *safely* is harder than it seems—which I was reminded of as I wrote this episode. (Rarely have I been so grateful for Rust’s string handling!) We’re going to have a function, `concat_strings`, which takes in two strings from a C ABI and returns another string back to the C API. (Remember, this works equally well for any language with a C API.) I’ve put the full code sample in the show notes, and you should read it. Here, I’m just going to talk through the function signature and the things we need to do to make this work correctly. On the Rust side, the function signature is: ```rust #[no_mangle] pub extern "C" fn concat_strings(first: *const c_char, second: *const c_char) -> *mut c_char { // ... } ``` The reason we’re taking pointers to `c_char`s is that C doesn’t actually have a notion of strings as such—it just has arrays of characters. A “string” is just a pointer to such an array, terminated by a null character. Now, since we’re taking in data from C, this is totally untrustworthy. We need to start by checking that the pointers aren’t `null`, and then we need to convert the C-style array of `char`s into a type Rust can work with safely. In an `unsafe` block, we’ll `assert!` that both pointers are not null, then use `CStr::from_ptr` to convert the pointer into Rust’s special type for C strings. `CStr` is the reference type, and `CString` the owned type, analogous to `str` and `String` respectively. And once you have a `CStr` or `CString`, you can convert it into a regular `String`—but with a cost for checking that it’s valid UTF-8. We don’t need to do that here, because we’re just sending it right back across the FFI boundary, but if we were going to work with the string internally in Rust code beyond this, that would be worth doing. Here, we take those two `CStr`s and turn them into slices of `u8`, drop each one’s terminating null byte, and then concatenate them and a single null byte with `std::slice::concat`. Then we create a new, owned `CString` from the result. This allocates the space on the Rust side for the string, which we’ll need to deal with in a minute. For sending it back across the boundary, though, we’ll just call `.into_raw()` on the `CString` and return that. That turns it into the `*mut c_char` that C needs to interact with it. Two important notes here: 1. This isn't actually the *right* way to do this in terms of idiomatic C APIs. Normally we would want to ask the caller to pass in a pointer to a buffer with enough space allocated for the concatenation, and would return an error code with `0` for success and a different number otherwise. However, it’s a useful example, so I did it this way anyway! 2. We’re returning a mutable pointer because we’re handing it back to a C API to do with as it will. (Even if we declared it as `char const * const`, the caller could choose to ignore it. Modern C compilers will *warn* about this, and you should listen… but they won’t *stop* you.) Now, the last thing here: Rust allocated the string, so Rust needs to free it. If you call `free` on the C side, or use the normal garbage collection mechanics in a language with a garbage collector, you will cause a memory leak, because the internal layout of a `CString` is a `Box<[u8]>`, and we need to make sure that gets deallocated correctly. We handle this by providing a `free_rust_string` function, which uses `CString::from_raw` to make sure everything gets dropped appropriately when it goes out of scope… which it does *immediately* because we don’t do anything else with it. This is the basic pattern for *all* rich data types going back and forth across the C FFI boundary in Rust. Arguments coming in as pointers need to be checked that they’re not `null`, since `null` pointers are not part of safe Rust. And when we allocate on the Rust side, we also need to *free* on the Rust side. These kinds of things are constraints you must document, and document *loudly* for any consumers of your library… including yourself! This is the key with all unsafe code, including by definition all FFI: you have to do the work that the Rust compiler does for you with safe code. ### Structs Moving on to structs, basically everything I just said about strings applies identically—which shouldn’t be a big surprise since `String` *is* a struct. Imagine my go-to example of a `Point`, with `x` and `y` fields. We can define that so it can be shared across the FFI boundary freely, by writing it with `#[repr(C)]` on the struct definition. Then we can write the corresponding C struct definition, and use it on either side of the language boundary. In this mode, we can start by declaring a `Point` on the C side and initializing its values to whatever we wish. Then, if we want to translate it from one location to another but on the Rust side, we can write a `point_translate` function just like our `concat_strings` function. ```rust #[no_mangle] pub external fn point_translate(point: *mut Point, by_x: c_float, by_y: c_float) { } ``` That function need to take the mutable pointer, check that it isn’t null, and then dereference it—which is `unsafe`!—to get an actual Rust reference to a `Point`. Then we can perform the translation in a normal Rustic way, like `point.translate()`. We don’t have to do anything special once we’re done, because C doesn’t have any notion of ownership, and from the Rust perspective we relinquish the borrow as soon as we’re done. But of course, we can also simply mutate it in place on the C side (and the code sample does exactly that!). #### Opaque pointers This is *not* optimal. We’re back to having shared mutable state, and that *across a language boundary*. At that point, we pretty much might as well just write it in C! What we can do instead is define opaque pointers. We expose the *existence* of the type, but we *don't* make it `#[repr(C)]` and we *don't* expose its internal fields at all. When we declare it on the C side, we declare it with no details at all: ```c typedef struct opaque_point opaque_point_t; ``` Then on the Rust side, we write our `OpaquePoint` exactly like the `Point` we wrote earlier, but the fields can be private… and there is no way to construct one directly on the C side, and no way to *modify* it on the C side. Instead, we add and expose another function on the Rust side. It has the signature: ```rust #[no_mangle] pub fn opaque_point_new(x: c_float, y: c_float) -> *mut OpaquePoint { Box::into_raw(Box::new(OpaquePoint { x, y })) } ``` To make it return that mutable pointer to an `OpaquePoint`, we create the instance like we usually would in Rust, wrap that in a `Box`, and then call the associated function `Box::into_raw` on the result. This gives us the pointer we need. We’ll also need a new function that we can use to describe the point’s value, since we don’t have access to its internals. We can combine a bunch of the other pieces we’ve seen already: implement `Display` for the type like any other, and then expose a `opaque_point_describe` function which takes a pointer to an `OpaquePoint`, then generate a `CString` from a the display formatter and return a reference to that `CString`. Finally we’re responsible to call free for any string we get that way *and* for the `OpaquePoint` when we’re done with it. We already have the `free_rust_string` function from earlier. Our `opaque_point_free` function will invert the process by which we got the pointer. As with strings, if it’s already `null`, we ignore it. If not, we do the `unsafe` operation `Box::from_raw`, and then do nothing; it properly executes its `Drop` implementation as soon as it goes out of scope, cleaning up both the allocated `OpaquePoint` *and* the `Box` wrapping it. Opaque types like this are a *super* useful primitive for making sure that we can expose Rust types to other languages while still actually maintaining all the invariants required for Rust to be *useful*. ### Other rich data types Before we wrap up, I want to survey three other types you should understand for FFI: unions, enums, and tuples. #### Unions C also has a kind of type that *safe* Rust doesn’t: unions. A union is kind of like an enum: it’s a single type which can represent a variety of different shapes. However, Rust’s enums are checked by the compiler: they are tagged and can be differentiated based on that tag. For example, you can think of the `Result` type as being a *union* of the two types it contains, with a tag specifying whether it’s the `Ok` value or the `Err` value. You write a union like this: ```rust union IntOrFloat { int: i32, float: f32, } ``` Once you’ve written that, you can create a union with syntax like struct initializer syntax, but you can only assign one of those variants: `IntOrFloat { int: 42 }` *or* `IntOrFloat { float: 0.5 }`. Once you have a union, accessing its internals requires an `unsafe` block, because you can access `int` or `float` (in this example) regardless of which one is actually defined… and so you can hose yourself very badly. The show notes have a sample implementation of an `Either` union type, which is very similar to `Result`. The main thing to take away here is that Rust’s union types interoperate correctly with C’s unions as long as you mark it as `#[repr(C)]` at the Rust type definition. #### Enums The *other* reason you might care about union types is that Rust enums interoperate with C using unions—because C’s enum types aren’t up to the task, since they’re essentially just names for integer values. If you put `[repr(C)]` on a Rust enum, it will be laid out as a union, with a Rust enum defining the tags, and structs for each variant. You’ll still need to do the work of defining these types on the C side, but this way you can impose some type-safety on enum interop. There are some more important details in [RFC #2195], which defined all of this, so I encourage you to read it! [RFC #2195]: https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md #### Tuples C also has no notion of a *tuple*, so languages consuming Rust via C APIs can’t interact with Rust tuples—even if the language in question *does* have its own notion of tuples. You can work around this by using a full-on `struct` to pass data back and forth, with conversions between your tuples and that struct type. The distinction between a tuple and a tuple struct is important here: tuples are anonymous types, while tuple structs have type names, which lets us write corresponding types in C for them, using index-style names for the fields: `_0`, `_1`, etc. ## Outro There is of course far more that could be said about this, but that should be enough to get you started! And next week, I’ll be back with a Crates You Should Know episode diving into a bunch of crates that make all of this *way* easier. ### Patreon Sponsors Thanks as always to this month’s $10-or-more sponsors: - Arun Kulshreshtha - Matt Rudder - Soren Bramer Schmidt - Dan Abrams - Oluseyi Sonaiya - Anthony Deschamps - Evan Stoll - Nick Gideo - Dominic Cooney - Embark Studios - Scott Moeller - Benjamin Manns - Daniel Mason - Jonathan Knapp - Nick Stevens - Jeff May - Behnam Esfahbod - Johan Andersson - Nathan Sculli - James Hagans II - John Rudnick - Zach Peters - Chip - Jerome Froelich - Andrew Dirksen - Joseph Schrag - Brian McCallister - Bryan Stitt - Raph Levien - Nicolas Pochet - Daniel Bornkessel (April only) - Ryan Osial - Jason Bowen - Jako Danar - Michael Mc Donnell - Adam Green - Alexander Payne - Rob Tsuk - David Carroll - Ramon Buckland - Martin Heuschober - Peter Tillemans - Paul Naranja - Graham Wihlidal - Ola Fadeyi - Cristian Paul - Daniel Collin ### Show info You can sponsor the show at patreon.com/newrustacean or via other services listed on the show website, . There, you’ll also find show notes, including links to things I talk about, scripts, code samples, and interview transcripts. The notes for *this* episode are at . Please recommend the show to others if you like it, whether in person, via your podcast directory, or in various media online! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending men an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/interview/diesel-1.0/master.md ================================================ # News: Rust 1.23 Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is an interview with Sean Griffin, on the development and release of Diesel 1.0. ## Outro And that’s a wrap—but that’s plenty! * Aaron Turon * Alexander Payne * Anthony Deschamps * Chris Palmer * Christopher Giffard * Behnam Esfahbod * Dan Abrams * Daniel Collin * David W. Allen * Guido Hoermann * Hans Fjällemark * John Rudnick * Matt Rudder * Nathan Sculli * Nick Stevens * Peter Tillemans * Olaf Leidinger * Oluseyi Sonaiya * Raph Levien * and Vesa Khailavirta If you're enjoying the show, please let others know about it in person or on social media, rate and review in your favorite podcast directory, or, if you're feeling extra generous, by sending some financial support for the show my way at Patreon.com/newrustacean or as a one-off via any of a number of other services I've listed on the show website: newrustacean.com. NewRustacean.com also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/interview/diesel-1.0/part-1.md ================================================ # Interview: Diesel 1.0, with Sean Griffin, Part 1 Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is part one of an interview with Sean Griffin, on the development and release of Diesel 1.0. ## Outro And that’s a wrap—but that’s plenty! * Aaron Turon * Alexander Payne * Anthony Deschamps * Chris Palmer * Christopher Giffard * Behnam Esfahbod * Dan Abrams * Daniel Collin * David W. Allen * Guido Hoermann * Hans Fjällemark * John Rudnick * Matt Rudder * Nathan Sculli * Nick Stevens * Peter Tillemans * Olaf Leidinger * Oluseyi Sonaiya * Raph Levien * and Vesa Khailavirta If you're enjoying the show, please let others know about it in person or on social media, rate and review in your favorite podcast directory, or, if you're feeling extra generous, by sending some financial support for the show my way at Patreon.com/newrustacean or as a one-off via any of a number of other services I've listed on the show website: newrustacean.com. NewRustacean.com also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/interview/diesel-1.0/part-2.md ================================================ # Interview: Diesel 1.0, with Sean Griffin, Part 2 Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is part two of an interview with Sean Griffin, on the development and release of Diesel 1.0. ## Outro And that’s a wrap—but that’s plenty! * Aaron Turon * Alexander Payne * Anthony Deschamps * Chris Palmer * Christopher Giffard * Behnam Esfahbod * Dan Abrams * Daniel Collin * David W. Allen * Guido Hoermann * Hans Fjällemark * John Rudnick * Matt Rudder * Nathan Sculli * Nick Stevens * Peter Tillemans * Olaf Leidinger * Oluseyi Sonaiya * Raph Levien * and Vesa Khailavirta If you're enjoying the show, please let others know about it in person or on social media, rate and review in your favorite podcast directory, or, if you're feeling extra generous, by sending some financial support for the show my way at Patreon.com/newrustacean or as a one-off via any of a number of other services I've listed on the show website: newrustacean.com. NewRustacean.com also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/interview-1-part-1-script.md ================================================ Closing ------- ...if you want to hear Sean answer that question, you'll have to come back for part 2, which should be up next week! ### Sponsors Thanks to Hamza Sheikh and Chris Palmer for sponsoring the show this month! You can see a full list of sponsors in the show notes. If *you'd* like to sponsor the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at Venmo, Dwolla, or cash.me. ### Follow/support You can find links to each of those, to the other things Sean and I mentioned on the show, and more at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. You can help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend! Thanks to everyone who's added corrections and fixed typos in the show notes; pull requests are great. I also love hearing from you! Definitely say hi on social media, add your thoughts in the thread for the episode on the Rust user forum at users.rust-lang.org, or shoot me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/interview-1-part-2-script.md ================================================ Opening ------- Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is *Interview 1: Sean Griffin, Part 2*. In Part 1, Sean and I talked about his background, some of his work building the Diesel ORM and his intent to build a Rustic web framework. Here in Part 2, we get down into the nitty-gritty details of Rust's type system---some of its strengths and weaknesses, and some of the things we might hope to see it do in the future. If you're less familiar with some of the terminology, definitely take a look at the show notes at newrustacean.com, as I've provided helpful links with details and explanations of many of the details we get into. And now, back into it! ... Closing ------- I hope you've enjoyed this first interview! Our next couple episodes will focus on Rust's type system in general and on those pesky lifetimes we keep mentioning but not actually talking about. We'll have more interviews on a semi-regular basis in the future, but for now, it's back to the nitty-gritty details of learning Rust. And keep your ears open: I have a non-trivial project I'll be starting in Rust in the next few weeks, which should provide a lot of interesting topics as well. ### Sponsors Thanks to Hamza Sheikh and Chris Palmer for sponsoring the show this month! You can see a full list of sponsors in the show notes. If *you'd* like to support the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at Venmo, Dwolla, or cash.me. ### Follow/support You can find links to each of those, to the many things Sean and I talked about on the show, and notes and more at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. You can help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend! Thanks to everyone who's added corrections and fixed typos in the show notes; pull requests are great. I also love hearing from you! Definitely say hi on social media, add your thoughts in the thread for the episode on the Rust user forum at users.rust-lang.org, or shoot me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/interview-3-script.md ================================================ ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is *Interview 3: Carol Goulding.* ## Outro I hope you enjoyed the interview as much as I did—lots of great thoughts from Carol! You can find links to the various topics we discussed on the episode, as well as all previous episodes, at newrustacean.com. Thanks again to Chris Palmer, Daniel Collin, Raph Levien, Stephen Murawski, and Vesa Khailavirta, and all the other sponsors for helping make the show possible! You can see a full list of sponsors in the show notes, and the top tier of sponsors on a dedicated page on the website. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at a variety of other services listed at the show website. I'll have more to say on sponsorship specifically in an upcoming podcast *about the podcast* in a week or two! You can follow the show on Twitter \@newrustacean, or follow me there \@chriskrycho. If you enjoyed the show, please help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, sharing it online, or just telling a friend! Also, please do respond on social media, in the threads for the episode on the Rust user forum or on Reddit, or via email at hello@newrustacean.com. I love hearing from you! Until next time, happy coding! ================================================ FILE: docs/interview-4-part-1.md ================================================ # RLS Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 show about learning the Rust programming language. This is *Interview 4: Jonathan Turner—Part 1*. In this first part we talk about Jonathan's programming background, how he ended up working on Rust, and the ways he has helped start pushing the language toward better and better usability. ... ## Closing And that's a wrap on the *first* part of this episode. There's a lot more where it came from, though: there are two more parts coming. Like this bit from the next episode: {>> awesome bit from second part <<} Thanks to: - Anthony Deschamps - Christopher Giffard - Chris Palmer - Dan Abrams - Daniel Collin - Matt Rudder - Ben Whitley - Peter Tillemans - Philipp Keller - Raph Levien - and Vesa Khailavirta for sponsoring the show this month. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website, or if you're a company interested in advertising to developers, get in touch! ### Info As always, you can find show notes and links for this episode and previous episodes, code samples, and more at NewRustacean.com. You can follow the show on Twitter @newrustacean; you can follow me there @chriskrycho; and you can follow Jonathan there @jntrnr. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use. I'd love to hear your feedback, as well as suggestions for topics, interviewees, and so on, in the threads for the episode on the Rust user forum or Hacker News. I also love getting email---you can send me a note at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/interview-4-part-2.md ================================================ Hello, I'm Chris Krycho, and this is the New Rustacean podcast: a show about learning the Rust Programming Language. This is Interview 4: Jonathan Turner, Part 2. In this second of three parts, we talk about Rust's role in bringing together the best parts of systems and higher-level languages, and improving the usability of Rust. *** Two parts down! But if you thought there were some interesting tidbits in this second part, just wait for the finale, when Jonathan throws some *amazing* ideas out there for the future of Rust tooling: Thanks to: - Anthony Deschamps - Christopher Giffard - Chris Palmer - Dan Abrams - Daniel Collin - Matt Rudder - Ben Whitley - Peter Tillemans - Philipp Keller - Raph Levien - and Vesa Khailavirta for sponsoring the show this month. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website, or if you're a company interested in advertising to developers, get in touch! ### Info As always, you can find show notes and links for this episode and previous episodes, code samples, and more at NewRustacean.com. You can follow the show on Twitter @newrustacean; you can follow me there @chriskrycho; and you can follow Jonathan there @jntrnr. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use. I'd love to hear your feedback, as well as suggestions for topics, interviewees, and so on, in the threads for the episode on the Rust user forum or Hacker News. I also love getting email---you can send me a note at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/interview-4-part-3.md ================================================ Hello, I'm Chris Krycho, and this is the New Rustacean podcast, a show about the Rust programming language. This is Interview 4, Part 3: Jonathan Turner. In this final part of the interview, Jonathan and I talk about future work on the Rust Language Server, on improvements to the Rust language itself, and a bit about Servo. So let's get back into it! *** So that wraps up a fantastic interview. I'm looking forward to diving back into our teaching episodes (and being back on a more even schedule: the last month has been a whirlwind of travel and house-buying and more). Thanks to: - Anthony Deschamps - Behnam Esfahbod - Christopher Giffard - Chris Palmer - Dan Abrams - Daniel Collin - Matt Rudder - Ben Whitley - Peter Tillemans - Philipp Keller - Raph Levien - and Vesa Khailavirta for sponsoring the show this month. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website, or if you're a company interested in advertising to developers, get in touch! ### Info As always, you can find show notes and links for this episode and previous episodes, code samples, and more at NewRustacean.com. You can follow the show on Twitter @newrustacean; you can follow me there @chriskrycho; and you can follow Jonathan there @jntrnr. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use. I'd love to hear your feedback, as well as suggestions for topics, interviewees, and so on, in the threads for the episode on the Rust user forum or Hacker News. I also love getting email---you can send me a note at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/interview-4-sponsors.md ================================================ # RLS Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 show about learning the Rust programming language. This is *Interview 4: Jonathan Turner*. A quick word for my sponsors who get to listen to this episode all in one piece (rather than broken up into parts as in the regular show feed): I hope to make more of these special-format versions of episodes as a way to say thank you in the future. I expect I'll put this up on the main interview page once all the other parts are released, but it'll never actually be in the feed, and you'll all get it about a full month in advance. *Thanks so much for sponsoring the show!* And now, into the interview! ## Closing Thanks to: - Anthony Deschamps - Christopher Giffard - Chris Palmer - Dan Abrams - Daniel Collin - Matt Rudder - Ben Whitley - Peter Tillemans - Philipp Keller - Raph Levien - and Vesa Khailavirta who all support the show with at least $10 a month. But thanks to *all* of you sponsors—I hope you enjoyed having this special full-length episode. ### Info As always, you can find show notes and links for this episode and previous episodes, code samples, and more at NewRustacean.com. You can follow the show on Twitter @newrustacean; you can follow me there @chriskrycho; and you can follow Jonathan there @jntrnr. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use. I'd love to hear your feedback, as well as suggestions for topics, interviewees, and so on, in the threads for the episode on the Rust user forum or Hacker News. I also love getting email---you can send me a note at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/irr_2017/anna-liao.md ================================================ # Increasing Rust's Reach: Anna Liao Hello, I'm Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is an interview with Anna Liao, one of the participants in the Increasing Rust's Reach program. --- Transcript: coming soon! --- ## Outro Thanks so much to this month's $10-or-more sponsors: * Aaron Turon * Alexander Payne * Anthony Deschamps * Chris Palmer * Christopher Giffard * Behnam Esfahbod * Dan Abrams * Daniel Collin * David W. Allen * John Rudnick * Matt Rudder * Nathan Sculli * Nick Stevens * Peter Tillemans * Olaf Leidinger * Oluseyi Sonaiya * Raph Levien * and Vesa Khailavirta If you're enjoying the show, please let others know about it in person or on social media, rate and review in your favorite podcast directory, or, if you're feeling extra generous, by sending some financial support for the show my way at Patreon.com/newrustacean or as a one-off via any of a number of other services I've listed on the show website: newrustacean.com. NewRustacean.com also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/irr_2017/lee-baillie.md ================================================ # Increasing Rust's Reach: Lee Baillie Hello, I'm Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is an interview with Lee Baillie, one of the participants in the Increasing Rust's Reach program. --- Transcript: coming soon! --- ## Outro Thanks so much to this month's $10-or-more sponsors: * Aaron Turon * Alexander Payne * Anthony Deschamps * Chris Palmer * Christopher Giffard * Behnam Esfahbod * Dan Abrams * Daniel Collin * David W. Allen * John Rudnick * Matt Rudder * Nathan Sculli * Nick Stevens * Peter Tillemans * Olaf Leidinger * Oluseyi Sonaiya * Raph Levien * and Vesa Khailavirta If you're enjoying the show, please let others know about it in person or on social media, rate and review in your favorite podcast directory, or, if you're feeling extra generous, by sending some financial support for the show my way at Patreon.com/newrustacean or as a one-off via any of a number of other services I've listed on the show website: newrustacean.com. NewRustacean.com also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/irr_2017/matt-gathu.md ================================================ # Increasing Rust's Reach: Lee Baillie Hello, I'm Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is an interview with Matt Gathu, one of the participants in the Increasing Rust's Reach program. --- Transcript: coming soon! --- ## Outro Thanks so much to this month's $10-or-more sponsors: * Aaron Turon * Alexander Payne * Anthony Deschamps * Chris Palmer * Christopher Giffard * Behnam Esfahbod * Dan Abrams * Daniel Collin * David W. Allen * John Rudnick * Matt Rudder * Nathan Sculli * Nick Stevens * Peter Tillemans * Olaf Leidinger * Oluseyi Sonaiya * Raph Levien * and Vesa Khailavirta If you're enjoying the show, please let others know about it in person or on social media, rate and review in your favorite podcast directory, or, if you're feeling extra generous, by sending some financial support for the show my way at Patreon.com/newrustacean or as a one-off via any of a number of other services I've listed on the show website: newrustacean.com. NewRustacean.com also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/meta-2.md ================================================ # Meta 2: Two Milestones Hello, I'm Chris Krycho and this is New Rustacean: a podcast about the Rust programming language and the people who use it. This is Meta Episode 2: Two Milestones. ## 2 Years and 50 Episodes In a neat turn of events, the release of this episode marks a double milestone for the show. First, the day I'm releasing this episode is two years and a day since I released Episode 0: Hello World. It's hard for me to believe that it's been two and a half years since Rust 1.0 happened, much less that I've been doing this for two years. (If you're curious why I didn't release this episode *on* the anniversary of the show, well, keep listening.) Second, this is also the 50th episode of the show! So despite a bit of a hiatus late last year in the midst of a really crazy time with work and school, an average of about two episodes every month. That's a *lot* of detailed content, and I'm really delighted to see that the show continues to be useful to people picking up Rust, and I feel like, 50 episodes in, the show has found its rhythm. Over that time, I've heard from many a listener that the show has been one of the ways they've found their way into Rust—and I couldn't be more glad, because at the end of the day, that's the main thing I have ever wanted to accomplish: more happily productive Rustaceans! To every one of you who's ever sent me a note along those lines: *thank you.* Those notes have been a huge encouragement at times when I've felt burnt out on the work it takes to make this show the way I do, or when I've felt conflicted about working on this instead of just writing some Rust. Because one strange and surprising aspect of doing this show has been that I haven't written nearly as much Rust as many of you. No few of the people who got into Rust in part through this show are now far *more* expert in Rust than me! I only have limited time during the week, and an awful lot goes into producing a show like this. If you've watched my Lightning static site generator project, you know just *how* slowly my actual Rust code has moved. That's sad, in a way—but it's also all right by me in the end. There's a sense in which I've been able to create far more Rust code by helping *other* people learn the language than I ever could have written by myself. It's a tradeoff, but it's one I'm ultimately happy to make! I'll add that if there was a secondary goal of mine in doing New Rustacean, it was that this podcast would inspire others to do the same kind of thing with other languages, and I learned last week that it *has*. There's a relatively new podcast, about a month old, called JavaScript to Elm, which is explicitly modeled on New Rustacean—but focused on learning Elm as a JavaScript practioner. I'm humbled; I'm amazed; and I'm *so glad* that this other show exists. But I want to add: there's no reason a podcast like this couldn't exist for Idris or Elixir or any number of other languages. In fact, I rather wish it *did*, because I'd be a faithful listener. So please, if you're learning one of those and have the itch to share what you're learning, *start that show*, and then tell me about it so I can listen and learn along with you! ### Status of the Show As I've been thinking about these two milestones, it's occurred to me: this show is about learning the Rust programming language; but at this point it's also about more than that. So the name isn't going anywhere, and neither are the learning elements of most of the episodes. But attentive listeners will have noted that I changed up the intro a bit today, and that's here to stay: because this show is and is increasingly about not just the language but its users. About you. Again, that doesn't really mean a change in format. It just means recognizing what the show is already doing! I'm just going to keep at the swing of things, pushing out news episodes every six weeks, with the other episodes being a mix of tutorial episodes, "Crates You Should Know" episodes, and interviews—with the occasional bonus episode or meta episode like this thrown in for good measure! Speaking of interviews, I'm *hoping*—and we'll see if I can pull this off!—to do a bunch of mini-interviews with Rustaceans at Rust Belt Rust in late October. If you're going to be there, please drop me a note and maybe, just maybe, you'll end up on the show! ### Transcripts Another fun little tidbit I have to share—strictly speaking this is "news" but it seems like a fitting thing to note in this milestone episode—listeners (and occasionally non-listeners!) have long asked for show transcripts. Some of you may also know that the scripts for every non-interview episode are available on the GitHub repository for the show. That's not perfectly convenient however. As it turns out, Michael Gattozzi recently wrote an RFC (#1990) which proposed making it possible to use standalone Markdown documents as the documentation for a given item. The biggest use case for this is likely to be sharing the contents of README files with the root of a crate's documentation—that'll be a huge win. But it also means that, as soon as that lands on nightly Rust (which I use for the show notes so that the benchmarking examples work), I can use it to easily add transcripts to the episodes. I'll plan to just add a "Transcript" item to every episode, and link it in the show notes. I also have plans for getting transcripts of the interview episodes done! So keep your eyes open! ### Celebrate Finally: to celebrate hitting these two milestones, I'm doing two things: 1. **I'm doing a run of New Rustacean shirts!** They're being printed through Cotton Bureau. That means they should be of extremely high quality: I've never heard of anyone having any serious complaints about them (and in fact, their shirts seem to be top notch). In general, Cotton Bureau just seems to be a pretty thoughtful company. In fact, the reason the show went out today, instead of yesterday, the actual anniversary: Cotton Bureau only does releases on weekdays. And props to them for that: people need weekends. I'm *really* glad they only do shirt launches (with the people-work that entails) during the regular work week. There are three shirt variants you can grab, all of them with the full New Rustacean logo—rusty crab and the words "New Rustacean"—printed on the front. One is a white unisex hoodie. The others are white and dark gray t-shirts, both available in traditional men's and women's cuts. I *think* I'm going to get the dark gray t-shirt, but honestly, I'm torn: all of these designs genuinely look amazing to me. You can see the designs in the show notes. I've put a link to buy the shirt in the show notes and I will also tweet it out every day the campaign is running to make it easy to find! The campaign runs for the next two weeks—so, today, September 5 through October 8. After that, the first run will be complete. The design does stay on the Cotton Bureau website, and if there's large enough demand at a later date, they will do a run again, but there's no guarantee that will ever be the case, so if you want this shirt I'd suggest getting it now! I've timed this partly in hopes that people will be able to get these in time to wear them to Rust Belt Rust. Fingers crossed; we'll see. 2. **I'm printing stickers!** I'm doing a mix of die-cut stickers and circular stickers. Both of those will have just the rusty crab New Rustacean logo (no words). Every sponsor of the show who wants one will get whichever of those they want mailed to them. (I'd just make them available to *everyone*, but good stickers are surprisingly expensive, and postage adds up, too! Still, if you're interested in some, let me know and we'll work something out. If nothing else, I'm happy to send you the patterns so you can print some up yourself!) I'm also going to have a bunch with me at Rust Belt Rust, and at any meetup I'm at in the future until I run out! I've included the images of the stickers in the show notes, too, so check them out. Shirts and stickers seemed like a pretty great way to celebrate two years to me—at a minimum, *I'm* excited to have a shirt to wear for one of the days at Rust Belt Rust, and to have some stickers to distribute to people. ## Outro Thanks so much to this month's $10-or-more sponsors: - Aaron Turon - Alexander Payne - Anthony Deschamps - Chris Palmer - Behnam Esfahbod - Dan Abrams - Daniel Collin - David W. Allen - Matt Rudder - Nathan Sculli - Nick Stevens - Peter Tillemans - Philipp Keller - Olaf Leidinger - Raph Levien - and Vesa Khailavirta As always—and this goes double on this anniversary episode—thanks as well to everyone who helps other people find the show, whether by just telling a friend, or by rating or reviewing it in iTunes or recommending it in another podcast directory, or by sharing it on social media! If you'd like to sponsor the show, you can do so by pledging monthly at Patreon.com/newrustacean, or by sending a one-off contribution my way at any of a number of services listed at newrustacean.com. You can find show notes for this episode, including links to docs and more for Rayon, at `newrustacean.com/show_notes/meta/_2_milestone/`. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Thank you all for listening and for making this such a fun ride so far. For the next 50 episodes… happy coding! ================================================ FILE: docs/meta-3.md ================================================ # Meta 3: Happy Coding! ## Intro Hello, I’m Chris Krycho, and this is the *final* episode of New Rustacean: a show about the Rust programming language and the people who use it. ## This is it! Yes, you heard that right: after three years and nine months of New Rustacean, this is the last episode of the show—or at least, the last *regular* episode of the show. To explain, I will tell you a story, and I will tell you a dream. And they are the same: the reason why I started learning Rust in the first place, and the story of this beautiful almost-four-year detour of a podcast which has come to be such a significant part of my life. There are two critical things you should know about me. Everything else in this story is a result of these two facts. First: I am… *particular* about the tools I use. Put another way: I am kind of a snob about software, especially UI. Second: from January 2013 through May 2017, I was enrolled in a Master of Divinity program—studying pastoral and practical theology. As is the case with most such degree programs, the school had a standard format for paper submissions. Documents had to be submitted in Microsoft Word documents with 12-pt Times New Roman, exactly per the 8th Edition of the Turabian style guide. But I am a snob, and Microsoft Word is, in my opinion, an capable-if-annoying desktop publishing application—and a *horrible* writing environment. For years before going to seminary, I had been working in plain-text formats for writing on my blog. I had long since become frustrated with What You See Is What You Get editors in tools like WordPress, and so had experimented with Textile, ReStructured Text, Markdown, and so on. There were (and are) a handful of very good plain text editing apps that simply got out of my way and let me *write* and then generate HTML to publish as I liked. I had fallen in love with this flow for a very simple reason: it let me focus on the words I was writing. This is still exactly the approach I use today—and not only for my blog, but also for the scripts of this show! So I had a writing workflow I liked, and a submission format I hated working in. I began poking around to see if there was a way to write Markdown and generate Word documents. The answer was *yes*, and I was delighted. Over the next few years, I assembled a whole chain of tools for writing academic papers, until I had a flow that let me research, write, and even cite documents in a way that worked much better than doing so in Word… while still handing in papers in the format my professors required. There was friction, but much less friction than working in Word, at least for my (admittedly fussy) aesthetic sense. A little over halfway through the program, having hit another one of those little friction points, I started wondering what it would take to build something myself that would do *exactly* what I wanted. Some of the pieces I had assembled were good but not optimized for this flow. Others were mediocre at best. And then, noodling on that idea, I realized: if I build a tool that made the research writing experience genuinely *good*, it might be a viable product in the world. *Lots* of people hate their writing workflows. The best options for people unwilling to put up with Word and EndNote involve command-line tools with arcane invocations. There was, I thought, something here worth pursuing. A genuinely great research writing environment *needs* to exist in the world, and I might just be able to make a reasonable living while making researchers’ lives better. It was early summer 2015. That’ll be important. I knew from the start that I wanted to design the app for eventual cross-platform support. I may be a Mac guy myself, but the audience of research writers is far broader. At the same time—perhaps unsurprising given my aforementioned *particularity* about UI, I have a firm commitment to fully native user interfaces with great performance. That ruled out Electron immediately, despite my background as a web developer. And just as importantly, “cross-platform” also meant targeting iOS, given how I did (and do) a lot of my writing; even if I had wanted to use Electron I couldn’t have. If I wanted to have shared business logic and target more than iOS and macOS, though, I would need to write shared libraries in a language that isn’t Objective-C or Swift. That meant—I thought—C or C++. But I’d also spent the previous six years writing C and C++… and I *really* didn’t want to write a layer of cross-platform business logic in either language. So I started looking around and asking friends if there was any alternative. One of them linked me to Rust. (Jeremy, if you happen to listen to this, *thank you*. You literally changed my life that day!) I spent a few hours that week working through [Rust by Example]. Right away, I knew three things: first, that Rust was exactly what I had been looking for; second, that *Rust was something really special*; and third, that there was a *lot* of work to do in the space. Remember the timeline! This was the summer of 2015—Rust had hit 1.0 a matter of weeks before I got this idea and started researching my options. [Rust by Example]: https://doc.rust-lang.org/stable/rust-by-example/ Over the next few months I kept mapping out the basic structure and design for this application. And I also was looking around everywhere for more resources about Rust. In particular, I was looking for a podcast, because then as now I do a lot of *learning* through podcasts, especially when runnning. There was one show about Rust at the time, and it didn’t seem like the hosts were going to keep it up for long. (They didn’t.) At the same time, I was *busy*, and I needed a way to help myself keep learning, and learning deeply and well. I had been producing my *other* main podcast, Winning Slowly for a year and a half, and so I thought: I bet I could do a podcast talking about *learning* Rust… The rest, as they say, is history… the history of this show. I did indeed learn Rust along the way. But a funny thing happens when you set out to make a show with the production quality and level of detail I do. As I noted in my “How the Sausage Gets Made” bonus episode a couple months ago: these episodes take a *huge* amount of time to put together. Each of the FFI episodes I just publishe, for example, were 20–25 hours of work. That’s on the high end for teaching episodes… but they weren’t outliers, either. The easiest episodes I produce—the news and bonus episodes—still take 4–6 hours. The shortest teaching episodes and the Crates You Should Know episodes take me a good 8–12 hours to produce. And I have a family and a church and a life that *isn’t* my day job *or* podcasting. Which has meant that, aside from filling up the pages of a notebook with thoughts and considerations along the way, I never made any progress on that dream of a genuinely great research writing environment. In fact, I barely made any progress even on much *smaller* projects, like the static site generator I started back in 2016. So: it’s time. I have covered every major topic on my list—though of course there will always be more to cover, because Rust is always growing and changing. (In just a few months, for example, async and await will be stable and things will move forward in a big way again!) Even as the language itself matures and the rate of change in *that* category hopefully slows over the years ahead, the community is exploding and the number of things I *could* cover with it. But the language itself I think I have done justice. And I still have that dream of building a great research writing environment. I have sunk the better part of four years into *teaching* Rust, but I’m ready to get back to the reason I started learning it in the first place. ## The Promise of Rust Four years ago, Rust was a dream and a promise: a dream of a world in which safe systems-level programming was possible and accessible to everyone, and a promise of stability as we all tried to make that a reality. There is still a long way to go… but that promise has been kept so far, and in a very real way, the dream is being fulfilled. People who always found C and C++ too intimidating, too unfamiliar, and at the end of the day too *dangerous* have found in Rust an opportunity to write systems-level software: systems-level both in performance and in the kinds of programs they can write. And the past four years of polishing have sanded off most of the rough edges that were there with 1.0: the many *incidental* points of difficulty. What is left, increasingly, is a language which exposes the real complexity of writing fast, safe software—but guides you through how to handle that complexity. The result is a real joy. Over the past few months at work, I have been working on the Volta project—a Node toolchain manager written in Rust—and it has just been delightful throughout. And other developers who had little or no experience with Rust before coming to the project are enjoying and excelling with it. The future for Rust is, I think, very bright. The last four years were, in so many ways, just the beginning: most people who will ever use Rust haven’t yet, most programs that will ever be written in Rust haven’t been yet, and the most important changes it brings to the industry haven’t been seen yet! I can’t wait to participate in it in a whole new way in the months and years ahead. ## Thanks Here at the end, I want to say a heart-felt thank you—to *everyone* who has supported the show in any way along the way. Credit here particularly goes to my wife Jaimie, who encouraged me when I thought about starting the project in the first place, and who has made the space for me to do the work a podcast of this sort requires. (Also, hosting [a video game podcast with her][ma] is far and away the most *fun* I have with any podcasting I do!) Second, my little girls have been enthusiastic fans all along the way. When I started this, they were just 3 and 1; this week, they turn 7 and 5. Third, my friend Stephen Carradini, with whom I host my *other* podcast, [Winning Slowly][ws], has been a steady encouragement as well. [ma]: https://massaffection.com [ws]: https://winningslowly.org Next, I want to say thank you to everyone who has sponsored the show along the way—you have made it far easier for my family to see this as a worthwhile investment of my time! That goes for both Parity and Manning as corporate sponsors, and it goes even more for the many of you who’ve chipped in everything from a single dollar to those of you who have, over the life of your contributions, given hundreds. Your generosity and support genuinely amaze me. And finally, thank you—thank you *so much*—to all of you who have *listened* to the show over the last years. So far as I can tell, the total number of people who have ever listened to the show is in the tens of thousands; and a good five or six thousand of you have been tuning in to every episode. Hundreds of you have emailed me over the life of the show. That amazes me. I remain profoundly grateful for the time and attention you have given me. ## Conclusion It’s not an exaggeration to say this show has changed the course of my life in so many ways. I am where I am today professionally in no small part because of this show. And if, as I hope, New Rustacean has also contributed in some small way to Rust’s success, I’m profoundly glad and grateful to have been a part of it. I’ll still be around on Twitter, both @chriskrycho and @newrustacean; and you can always email me at either hello@newrustacean.com or hello@chriskrycho.com. If you want to follow along with the research writing app project, I set up a mailing list for it at [buttondown.email/rewrite][rewrite]. If you want to *support* me as I do that, including getting *more* updates on than you will in the newsletter, you can do so at [patreon.com/chriskrycho][patreon]. As for New Rustacean itself: I expect to keep the show online indefinitely—my hosting costs are tiny, and so this will be here as long as I think it has value—so feel free to keep pointing people to it as a learning resource. I have of course paused all ongoing contributions, but if you decide to send me a thank-you via one of those *other* services listed on the show website, I will of course not complain. And on a final note, keep the show in your podcast app. I make no promise ever to post another episode here…but I also make no promise not to. If I have something I just *have* to say about Rust, well… you know… [rewrite]: https://buttondown.email/rewrite [patreon]: https://patreon.com/chriskrycho Thanks again for listening, and… happy coding. ================================================ FILE: docs/news/1-script.md ================================================ # One year and counting ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Episode 15: One year and counting*. ## News and Follow-Up - First, thanks again for your patience. For one thing, the end of the semester is a busy time---I wrote well over 10,000 words on philosophy of science and religion from a Christian perspective in the span of six days last week! For another, we've just shipped a brand new mobile web experience at Olo, and getting that out the door was no small endeavor! The summer should be a little more settled, though it will still include some travel and some school. - Second, and certainly of more interest to all Rustaceans: the first-ever RustConf has been announced! After last year's by all accounts very successful RustCamp, the good folks at Mozilla, Tilde.io, and a few other places are putting together a full-on conference in Portland, Oregon on September 10th, with a day of Rust training from core team members the preceding day. You better believe I'm submitting a talk proposal, and I'm hoping to be able to meet many of you there! - Third, Rust 1.9 came out this Thursday! I'll talk more about that in just a minute. ## Happy Birthday I originally planned to make this episode be a deep dive on smart pointer types like `Box`, `Vec`, `Rc`, `Arc`, and so on. And that episode is coming. However, as I started writing, I realized there is just a ton of *news* to cover, and so I thought I'd add another episode format to the show: summing up some of the big changes to the language, ecosystem and so on. These episodes will probably come every three to six months (and I have plenty to say on smart pointers, don't worry). So for starters, happy birthday to Rust! Rust hit 1.0 May 15, 2015, and here we are a year later with a growing community, quite a few companies using Rust in production, and an awful lots of progress on the language, the standard library, and many increasingly well-regarded other libraries out there. In the lead-up to that, there were a series of posts on the Rust blog which gave a great overview of where things stand and what's coming up both for the core language and for the ecosystem. I'm not so much going to go those pieces in detail (I'll just link them in the show notes so you can take a look) as briefly summarize them and then interact with them. I have to start by saying: I'm *really* excited about Rust. I mean, you knew that already from listening to this, but everything I'm about to talk about makes me extra enthusiastic. I also got to spend some time *writing* Rust for myself last night, for the first time in a couple months---with everything going on, I just haven't had a lot of spare cycles that way, but *wow* I enjoyed it. ### Rust proper So let's talk about the news in the Rust world! As usual, I'll link to the relevant blog posts, RFCs, etc. for everything I'm about to discuss. #### Rust 1.9 First up, Rust 1.9: just after the first birthday of Rust 1.0, we got the 9th minor language release. If you've watched any other language development process, this is nothing short of remarkable. Seriously: I know I gush about this a lot, but I would *love* to see other language communities adopt this kind of process. It means we get new things whenever they're ready, but without impacting our ability to keep working with the same codebase. Imagine getting a little bit nicer environment in Ruby or Python *every six weeks* but with nothing breaking. Imagine that with Java or C♯ or C++! It really is hard to overstate how big a deal this is. Rust 1.9 added a couple niceties: - Defining what a `panic!` should do. Now, you can specify whether it should kill the program with a full stack dump, or whether you actually want to "catch" the panic. This lets you handle, for example, cross-thread panics where you need something to fail on a secondary thread but deal with it, including finishing the stack unwinding, on the main thread. It also lays the groundwork for letting programs specify more generally how to handle panics in the future, including just aborting everything with no unwinding or stack trace. - It also made the `#[deprecated]` annotation available to developers. This is a big deal for library authors: it lets them use the same machinery that's available to the standard library to say, "Hey, don't use this function/struct/enum/etc. Use this newer one instead; the old one will go away at the next major version bump." While we ultimately want to get to a point where library authors can introduce their *own* annotations, having this one be standardized from the core is a win regardless. - There are some nice performance improvements in the compiler (and as we'll discuss in a moment, there are a lot more of these coming in the next year!). - The ability to "specialize" the implementation of a given trait method has been put to use in the standard library for the first time. That functionality will become available in stable Rust soon, and when it does it'll allow a lot of neat performance improvements as well as some better ergonomics for trait methods in general. We'll talk more about trait methods and specialization in a future episode. - There are bunch of nice improvements and additions to the standard library, as usual. You can check out the release blog post and release notes (which I'll link in the show notes, of course) for details. #### MIR Now, for some *really* nerdy fun: compiler details! One of Rusts' biggest weak points since 1.0 (and before) has been its compile times. I've mentioned the "MIR," or "mid-level intermediate representation" effort briefly before, but it's *the* key change to the Rust compilation model that will speed up compilation times---because it's the piece that will let incremental compilation happen. If you're coming to Rust and your background is only with interpreted or just-in-time-compiled languages with a runtime (Python, Ruby, JavaScript, etc.), it might not be obvious that there are different approaches to compilation, only that the ahead-of-time compilation is different from the interpreted or just-in-time approaches. But in compiled languages, you can also distinguish between needing to compile the whole of some artifact every single time----whole-binary compilation---and being able to compile only the parts which have changed---incremental compilation. One of the reasons that C C++ can be compiled faster than Rust in the ordinary course of application development right now is that the compilers supports *incremental compilation*: when you rebuild after making some changes, all major C and C++ compilers---Clang, MSVC, GCC, Intel, etc.---can recompile and re-link *only* the parts which have changed. So if you change one line in one module in a hundred-thousand-line program, you only compile that one module, and relink it. That makes ordinary day-to-day compilation proceed *much* faster than if you had to recompile the whole thing every time. (The same thing is true of languages like C# or Java, or really any languages on the .NET or JVM platforms, with a mixed model: which are ahead-of-time compiled to byte code and then just-in-time compiled for execution. For that matter, the same is true of Elixir, running on the Erlang VM.) Unfortunately, Rust has historically *not* supported incremental implication. But the new mid-level intermediate representation stage in the compilation process will make it possible, and that in turn will dramatically improve compiler performance in the ordinary case. Working on things like Rust itself, or Servo, or Dropbox's new cloud storage engine back end, or Tilde's Skylight tool for Ruby, or really any large project, will have a much faster development iteration cycle once it lands, and Rust will be much more competitive with other languages in this area. So let's take a couple minutes and talk at a very high-level about how the Rust compiler behaves *today* and how it *will* behave in when the MIR changes ship. (That's *very* soon, because this effort has been in progress for about a year!) For starters, it's worth note that Rust uses the LLVM compiler set. LLVM stands for "low-level virtual machine," a name which is somewhat confusing. The project came out of Chris Lattner's Ph. D. work, and forms the foundation of Apple's compiler toolchain---first for ObjectiveC, C, and C++, and now also for Swift. However, that "low-level virtual machine" provides a compilation target which can be and has been used for *lots* of languages, now include Rust. It provides very powerful optimization analysis itself, so when you're building a new programming language, you don't have to understand *every* detail of what's required for optimizing your code---especially on multiple compilation targets. (You still have to understand a lot, of course.) Second, the basic flow of the Rust compiler goes something like this today: 0. Start with Rust source 1. Transform the Rust source to a high-level intermediate representation by parsing the source and desugaring it. - In the parsing step, the compiler reads the source and interprets it in terms of the tokens that make it up: the keywords, the operators, and - Desugaring takes the constructs in Rust which are "syntactic sugar" for something else and converts them into their more basic form. For example, we've talked about how the method call "dot" syntax is syntactic sugar before. If you had a struct named `Foo` and created an instance of it named `my_foo`, and called a method on it by typing something like `my_foo.bar()`, this would *desugar* into `Foo::bar(my_foo)`, because the first argument to methods is `self` and it's handed over implicitly. When the compiler has parsed the is done with this desugaring process for *all* the constructs like this (and there are a fair number), what you have left is the *high-level intermediate representation*. 2. The second step is to compile this high-level intermediate representation to LLVM intermediate representation (or IR). *Lots* of languages target this intermediate representation---anything compiled with LLVM, in fact. So if you're compiling C or C++ with Clang, or running the Swift compiler, or running the open-source .NET LLVM compiler for C# or F#, or using it as a front-end for Haskell or Java or Scala... well, you get the idea: it all ends up as LLVM IR. This IR is Today, in Rust, the step from the high-level intermediate representation to the LLVM intermediate representation is *huge*: - It does all the type checking. When you get one of those gnarly-but-super-helpful errors that tells you you tried to pass the wrong type to a function, it's coming out of this step in compilation. - It does the borrow checking. When the compiler complains that you tried to write data to something borrowed immutably somewhere else, it happens in this step. - It translates the parsed Rust source into the primitives used by the LLVM compiler. As you can imagine, given the list of languages that can use LLVM as a compilation tool, these are *much* lower-level primitives than the kinds of things you see in *any* high-level language. 3. The third major step is compiling the LLVM IR to the target binary. This has two major elements to it: - Optimizing! The LLVM compiler takes the LLVM IR and heavily optimizes it. You get the great performance you do out of Rust (or Objective C, or C++, or whatever else) compiled with LLVM because it has a really smart optimizer. (More on this in a minute, though!) - The optimization is target-specific: the compiler generates actual machine code for the specific architecture and OS kernel you requested, e.g. 64-bit Darwin for modern Macs, or 32-bit Windows NT for the stragglers still running XP, or any number of other targets. So that's how the Rust compiler has worked historically. With the addition of the mid-level intermediate representation, there's one more step in the middle. 0. You still start with Rust source, of course. 1. The first step is still generating the high-level IR, and this hasn't changed at all: it's still just parsing and desugaring. 2. The second step is the new one: generating mid-level intermediate representation. All the type-checking now happens in the transition between the high-level and mid-level intermediate representations. This new mid-level intermediate representation (MIR) is something like a super-simplified version of Rust. It transforms many of Rust's high-level constructs into much simpler constructs. Basically, it turns all the Rust code you're familiar with into (and here I'm quoting from the writeup on the Rust blog), "a set of data structures and a control flow graph." This means that we can deal with everything from panics to match expressions to loop expressions to iterator operations in the same basic representation. That lets us figure out things like: - what actually needs to be recompiled when we change some of our code - more flexible rules around borrowing that are still equally safe but easier to write - how the relationship between panics and iterators might play out - when and how we can "drop", i.e. destroy, a given instance safely And all of that *before* the final compilation step where we drop down to LLVM IR. 3. The third step is generating the LLVM IR. But because we moved some of those steps up into the HIR to MIR transformation, less happens here than before. We still do the borrow checking in this step. But we also add a *new* step as part of transitioning to the LLVM IR: optimization! Because the mid-level IR gives us a better internal representation of the Rust code, we can actually do some Rust-specific optimizations that weren't possible when we just went straight from HIR to LLVM IR. Rust has a really expressive type system, as we discussed in episode 11; adding this step will let the compiler take much better advantage of that type system for optimizations. LLVM optimizations by definition have to work for *everything*, and languages like Ada and Rust are, well, just a *little* bit different. Getting specific will help a lot. 4. The last step is the same as before: LLVM compiles its machine code to the target binary, doing those really valuable but more general LLVM optimizations along the way. So there's a lot there, but hopefully you understand Rust's compiler flow a little better and can see how the new mid-level intermediate representation will improve the day-to-day experience of using Rust for *all* developers, as well as make the language faster and more powerful going forward. One of the neatest things about this, in my opinion, is that if you go to play.rust-lang.org, you can actually *look at the MIR* generated by the compilation process, just like you can at the LLVM IR and the machine code. Super neat. ### Tooling Two other neat things to highlight from the Rust blog that have coincided roughly with Rust's birthday. #### Cargo One of Rust's greatest strengths from the 1.0 time forward has been Cargo and crates.io, which together form its package management and distribution system. It's not an exaggeration to say these are best in class. I use pip and PyPI for Python, and Bower and npm for JavaScript, on a *very* regular basis, and I've interacted regularly with other package management tools like NuGet and RubyGems. Cargo and crates.io come together to make something *really* special. When I talked about how easy it is to use Rust even for just little command line tools you need, a *huge* part of what makes that possible is Cargo, which manages the whole build and distribution cycle---from creating a new project, to building it, to shipping it as a usable library or installable program, to installing those programs on your own system, to enhancing the functionality of the build tooling with tools like racer for code completion or clippers for code quality analysis. And it does all of that without turning into the kind of nightmarish or hideously arcane interface you might have come to associate with other especially powerful command line tools (I'm looking at you, Git). Quoting from Yehuda Katz's blog post, the three pillars of Cargo's philosophy are: 1. Building, testing, and running projects should be predictable across environments and over time. 2. To the extent possible, indirect dependencies should be invisible to application authors. 3. Cargo should provide a shared workflow for the Rust ecosystem that aids the first two goals. If you've spent time with, say, npm lately, you know how big a deal goal #1 is. Predictable builds across environments and over time is... huge. My team at work has been bitten by non-deterministic build issues with npm over and over again in the last few months, and it's infuriating. Cargo makes strong guarantees that when you make a given build, you can reproduce it *exactly*. The second goal just means that if you use a library which uses another library, you shouldn't *normally* have to worry about it. But what if they depend on say, versions 0.2.0 and 0.3.0 of a library? Well, things get messy. Cargo already handles this better than a lot of package managers, but there's room for improvement here, and one of the goals for Cargo in the months ahead is to make those improvements. The last goal is a big one, and it's exactly what powers a lot of what I talked about back in Bonus Episode 4. If you have a powerful tool which has strong conventions that the community as a whole embraces, but which also lets you adjust it when those conventions don't match your specific needs... you have a recipe for huge success. It means you can write everything from an operating system to a tiny script-like tool with the same set of tools. Of course, it doesn't always mean you *should*: sometimes you should just use a shell script. But it's neat, and thoroughly empowering for the community, that you *can* do that. #### `rustup` The last bit for this episode is `rustup`, a new tool which will replace both the current rustup shell script, which is the default way to install Rust initially, and multirust, which is the current standard way to install multiple versions of Rust alongside each other. What makes this especially interesting is that the plan (and quite of bit of this already works) is for `rustup` to support not only installing and running different versions of the compiler but also managing cross-compiles. The day is coming when you might well be able to do the same kind of multi-target compilation with Rust you can do with Go or even Java---and in terms of making the language useful for the kinds of tools I discussed in Bonus Episode 4, that's *huge*. It also makes it way easier to write and distribute things like compiled extensions for Python, Ruby, Elixir, etc. And, as a particular point of interest for me as a web developer, one of the planned target architectures for cross-compilation is the in-progress WebAssembly spec. Imagine a day when you could write Rust, compile it, and run it in your browser instead of writing JavaScript. For this web developer and Rust fanboy, at least, that prospect is incredibly exciting. I'm not-so-quietly hoping to be doing just that, just because I can, sometime late this year. You can try `rustup` today by going to rustup.rs and downloading it. If you find bugs or run into issues with things that aren't documented yet, open an issue on the repository for it! And it's a small enough project that if you're looking for a good place to contribute to core Rust tooling, it's a good place to start. ## Closing I hope you've enjoyed this new format episode looking at some of the ongoing language changes and news in the Rust world. I'll only do this kind of thing every three to six months (unless some *really* big news happens, of course), but especially since this is the main (and maybe the only) Rust podcast out there, I thought it might be useful. On that note, if you know of another Rust podcast, interesting video content or blog posts, etc., tell me about it! I'm very interested in promoting other parts of the Rust community! In the next episode, I'll discuss those smart pointer types and what it looks like to use them in practice. The time after that, I have another interview headed your way from someone working on an interesting project with Rust! ### Sponsors Thanks to Chris Palmer, Hamza Sheikh, Daniel Collin, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at Venmo, Dwolla, cash.me, or Flattr. ### Follow You can find links to everything I mentioned at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you enjoy the show, please tell somebody about it. It also helps others discover the show if you leave a rating and review it on iTunes, recommend it in other podcast directories, or share it around on whatever social media you use. You can respond in the thread for the episode on the Rust user forum at users.rust-lang.org, or you can shoot me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/news/2-script.md ================================================ # Let's Talk Roadmap ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *News Episode 2: Let's Talk Roadmap*. ## Status update To listeners and especially sponsors who've waited patiently these last couple months, thanks so much for your patience. 2016 ended up being one of the most personally challenging years of my life, and a lot of stuff that happened earlier in the year resulted in tons of work piling up at the *end* of the year. I had no bandwidth whatsoever for anything but work and school. But it's my end-of-year vacation, and I'm not in class *or* working, so here we are! A news episode at last! I've also made a reasonable amount of progress on my "Lightning" static site generator project this week—it's still a long way from being ready to use, but a lot of the foundational pieces are in place now. You can follow along with that at github.com/chriskrycho/lightning-rs. Now, for news about *Rust*. ## 2016 2016 was a big year for Rust—not so much in terms of any huge features, but instead in terms of a lot of small wins. In addition to landing MIR and *starting* to reap some of the performance rewards from it discussed back in the first news episode, there are a bunch of other bits and pieces that have made Rust nicer to use. ### The language Here are a few of the biggest things to hit the language itself since May. (I mentioned a few of these in news sections of previous episodes, but it's worth collecting them all here to get a sense of the rest of the year as a whole): - **More options for handling `panic!`s:** Rust 1.9 and 1.10 together made it possible to define much more specifically how your application should behave in the face of panics. First, you can now catch panics and deal with them in a pre-specified way, which is useful for cross-thread or cross-language boundary issues. You can do that with the `std::panic` module. Second, you can choose to simply abort the process entirely, with no stack unwinding, when it makes sense---and that can decrease the size of your binary and make your compile times faster. Both of those tools are things you should explore carefully before applying them, because as always there are tradeoffs. But it's nice to have the tools when we need them. You can configure that in your Cargo configuration, or pass it explicitly as a command line flag. - Rust also got some **new and improved error output**. That comes in two parts: the introduction of a JSON-based output for smart text editors and IDEs to use, and a nicer error message format for users. The new JSON error format for editors means they can simply define how to handle the JSON payload instead of having to parse information out of a plain-text error. The new error format for users makes it far, *far* easier to understand your errors. For one, as the announcement blog post noted, it puts your code front and center, making it obvious where the errors actually are. The old format included that info, but often buried it in a wall of other text. That other text is still there, but it's arranged differently, so that the code which doesn't work is more obvious. I've appreciated this a *lot* in the last week as I've been hammering away at Lightning. - One of the big hopes for MIR landing was that we'd get **incrememental compilation**, which should speed up the develop-and-compile-and-test cycle dramatically. That feature hasn't *quite* landed on stable Rust yet, but it's coming! It's been in-development-and-available-on-nightly mode for several months now, and if you take a look at the GitHub milestone where work is being tracked, it's getting awfully close to landing the first phase on stable. - One of the other hopes for MIR is that it will enable better optimizations. There aren't a ton of these yet, but they're trickling in and they're adding up. A bunch of these landed in 1.13 and 1.14 in particular, so if you're interested in the details, you should take a look at those blog posts and release notes, which I've linked in the show notes. (The same is true for the bits I mentioned above, too, of course.) - Finally, and perhaps most intriguingly, 1.14 came with experimental support for WebAssembly. If you're not a web developer, you probably haven't heard of WebAssembly (and even if you *are* a web developer, it may not have crossed your radar yet). WebAssembly builds on work done in the browser space in the last few years, aiming to provide what its website describes as "a portable, size- and load-time-efficient format suitable for compilation to the web." Put another way, it's a way to compile a variety of languages to a high-performance representation (better than normal JavaScript by a considerable margin) that can run in contexts like browsers.You can actually do some pretty interesting things targeting the browser from Rust *now*, since that experimental support landed in 1.14. There's a long ways to go there on both the compilation front and the WebAssembly standard itself, but we've taken the first steps. ### `rustup` So let's say you wanted to play with WebAssembly: how would you do it? Well, a tool I mentioned as newly in beta in the last news episode has now made it to 1.0! `rustup` is now the officially recommended tool for managing your Rust installations. The tool lets you install any specific version of Rust, as well as grabbing the latest stable, beta, and nightly versions of the whole toolchain (including Cargo). It also supports installing more than one *target* for the compilation, and that's how you can compile to WebAssembly today. For *any* target supported by Rust, you can just type `rustup target add` followed by the name of the target. You may also need a couple other pieces to link to, but this actually gets you everything you need for cross-compilation for a *lot* of targets. So for WebAssembly, you need to install one other dependency, a tool called _emscripten_. Then you type `rustup target add wasm32-unknown-emscripten`, and you're off to the races, using your normal toolchain. You can do `cargo build --target wasm32-unknown-emscripten`, for example, to build a whole crate targeting WebAssembly. And you can do the same kind of thing if you're cross-compiling to Windows from Mac or Linux, for example---you just need to snag a few dependencies and you're off to the races, able to ship native binaries on every platform. If you'd like to see a fairly trivial but nonetheless interesting example of compiling for Windows from macOS, you can take a look at a blog post I wrote describing the process. Having `rustup` in our toolbelt for the years ahead is going to help a *ton* for cross-compiling. Anyone who's ever tried to do the same with C or C++ will appreciate this a lot. And anyone who's ever tried to ship standalone binaries of Ruby or Python programs knows that that has its own challenges. Having the ability to do this *and* integrate easily with existing C libraries puts Rust in a pretty unique spot. You should see more work on this, and on "xargo", the cross-compilation tooling around Cargo, in the months and years ahead—but the truth is, it's already in a pretty marvelous spot, and only getting better. ### Cargo Speaking of Cargo, it's mostly just chugged along steadily over the past few months, but it did get one very significant new feature this year: the ability to manage a *workspace*. The idea is: you often have a set of related crates which you want to be distributed and compiled separately, but which work together closely, and which you want to be able to use with each other easily. A workspace lets you define exactly that setup, without having to do all of the development in a single version control repository or a single file tree. To define a workspace, you just have to add a "workspace" section in the main crate's `Cargo.toml` file, and then specify the root workspace in each child crate's own `Cargo.toml` file. (You can also optionally specify the child crates in the main crate, but you don't have to.) Also, handily enough, you don't even have to specify it for the child crates if they *do* live in a single file tree (e.g as git subrepositories or similar); you only have to specify them if they're not in that "conventional" location. When you `cargo build` any of the child crates, the compiled binaries end up in the relevant target directory for the parent crate, ready to be linked into the final application. And when you `cargo build` the parent crate, it will pull those dependencies in together just as if they were located elsewhere, but with the binaries already available for linkage, it will speed up the process substantially (and make organizing these kinds of projects a lot easier along the way). This isn't necessarily something every project will deal with, but if it's something *your* project deals with, you'll definitely be happy to have it. (And it's the kind of thing that many projects will *eventually* run into as they grow in scale. So you may not need it today, but you might *tomorrow*.) ### Rust Language Service The last *big* thing that is worth mentioning as a 2016 development is the Rust Language Service. This one's a huge "work-in-progress": we haven't seen a lot publicly since it was demoed at RustConf, but it's been seeing steady, if quiet, incremental development since then. The Rust Language Service is a piece of software that sits between your editor---whether that's something like the JetBrains IDE plugin or something like Vim---and provides information for everything from autocomplete suggestions to refactoring. Historically, these kinds of things were done on a per-IDE or per-editor basis, and that meant a lot of work to be redone for every editor. With their work on TypeScript, Microsoft took a different tack: they created a language service that any editor could connect to and get top-notch information for all of those pieces of IDE-level functionality: syntax checking, type checking, finding usages, finding definitions, doing renames, etc. If you've ever used the official TypeScript plugins for VS Code, Atom, Sublime Text, etc., it's using that service---and it can be very, very good; it's easily one of the best editing experiences I've ever had in any programming language. One of the developers who was responsible for creating the TypeScript language service is Jonathan Turner, now an employee of Mozilla working on (wait for it...) the *Rust Language Service*, which will bring all that same shiny IDE-type goodness to *our* editing experience. Of all the things that should land in 2017, a beta- or even stable release of the RLS could be one of the biggest game-changers. When you're just getting going, this kind of things is invaluable because it helps you explore the space. When you're an expert, it speeds you up and increases your productivity a *lot*---especially when doing refactoring work, where it beats the pants off of either find-and-replace or making a change and then working through a list of compiler errors on the command line. Knowing you have a type error in roughly real-time in your editor is *fantastic*. Tools like `cargo check` can give you some of those benefits today, but they get slower and slower the larger your project gets, because they depend on doing actual compilation work. Suffice it to say I'm excited about the work that's already been done here, and even more so about what's ahead. ### The community I'm certainly biased, but I think of the other big changes that came out of 2016 was a new, hard commitment to documenting all new language and standard library features. I'm biased, of course, because I wrote the RFC that articulated both the need and---eventually, after 80-some-odd comments---the process we'll be using to tackle this going forward. But bias aside, I think it's a wonderful comment on the Rust community that the discussion was entirely about *how to tackle the problem*, not *whether it was a good idea*. If you've ever gone hunting for information on language features introduced since Rust 1.0 came out, you've probably discovered that a lot of those features aren't documented anywhere except in the RFCs which proposed them. You've probably also noticed that the Rust reference is extremely out of date. In fact, the reference currently includes a note indicating that it *tends* to be out of date---direct quote! So when I proposed that all new features be required to be documented before they become stable, that means there's a lot of work to be done. But again: the response was "Let's do this! Now, how?" And that's already started to play out as features preparing to merge to stable have been getting documented. We have a lot of work to do here in 2017---more on that in a minute. But the big takeaway for me here was, again: the Rust community has its collective head on straight about these things. ## 2017 For 2017, the Rust core team developed a set of overall goals to guide the development of the language. You can see the full proposal and discussion at the RFC (linked in the show notes) for the year goals. Here, I'll just quote from the overview and discuss a little of what it should mean. > This year's focus is improving Rust's productivity, while retaining its emphasis on fast, reliable code. At a high level, by the end of 2017: > > - Rust should have a lower learning curve > - Rust should have a pleasant edit-compile-debug cycle > - Rust should provide a solid, but basic IDE experience > - Rust should provide easy access to high quality crates > - Rust should be well-equipped for writing robust, high-scale servers > - Rust should have 1.0-level crates for essential tasks > - Rust should integrate easily into large build systems > - Rust's community should provide mentoring at all levels > > In addition, we should make significant strides in exploring two areas where we're not quite ready to set out specific goals: > > - Integration with other languages, running the gamut from C to JavaScript > - Usage in resource-constrained environments The big takeaway here is that the goal isn't shiny new, big bang features, but instead of a bunch of sort of "infrastructural" improvements. Things like the previously mentioned Rust Language Service fit right into a bunch of these. The other big points of interest---high-quality, 1.0-level crates; being well equipped for servers; and being able to integrate into large build systems---will make a big difference for making it possible for companies (maybe including yours) to adopt Rust in production. I don't really expect that to be the case for my current employer (though who knows? If an opportunity comes up for us to write something in Rust you better believe I'll be taking it). You can expect to see 2017 be the year where the "primitives" for servers all get solidified as projects like the Futures library and Tokio mature. Then in turn, mid to late in the year you will probably start seeing some more easily usable mid-to-high-level web frameworks appear or substantially mature. For an example of one mid-level framework that just launched, and which should be able to take advantage of the low-level work provided by Futures and Tokio this coming year, you can (and should!) check out the recently announced Rocket framework, which looks quite nice. (I'll of course have links to all of those in the show notes.) One reason I'm really excited about *these* features is that they hit my niche: web development with Rust is a fascinating corner. One of my personal Rust goals for 2017---besides getting my Lightning project working---is to do (at least a large chunk of) the work necessary to "implement" RFC 1636 and get all our existing features documented. I also expect to chip in here and there with documenting new language features as they land. If you're looking for a way to jump in, this is a great spot to help: check out the list of undocumented features I'm putting together on Rust issue #38643---I'll link it in the show notes. I think it also fits well with these overall goals, in that *having a lower learning curve* certainly includes having all the language features documented! ## Closing So that gives you a pretty good idea of where Rust has been in the latter half of 2016 and a little preview of where we're going. 2017 looks like it should be a great year of just making things nicer and easier to use all around. Thanks for following along with me this year. In 2017 you can look forward to a lot more New Rustacean---interviews, the new Crates You Should Know format, the occasional bonus episode, news episodes, and of course the dedicated topic episodes. January should hopefully see at least one Crates You Should Know and one topic episode! ### Sponsors Thanks to - Chris Palmer - Matt Rudder - Ben Whitley - Peter Tillemans - Steven Murawski - Raph Levien - Daniel Collin - and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes. If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website. ### Follow Speaking of the website... you can also find links to everything I mentioned on the show today at NewRustacean.com. You can follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you enjoy the show, please tell somebody about it. It also helps others discover the show if you leave a rating and review it on iTunes, recommend it in other podcast directories, or share it around on whatever social media you use. You can respond in the thread for the episode on the Rust user forum at users.rust-lang.org, or you can shoot me an email at hello@newrustacean.com. At the end of this year, it seems particularly appropriate to say: Thank you so much, everyone who has sponsored the show---whether through Patreon or any of those other channels. Thanks as well to all of you who have sent me kind and encouraging notes. This show has been a bright note in the midst of a year that was, at times, extremely challenging. And your support---verbal no less than financial---encourages me to keep working to craft this into the best show I can make. Finally, thank you to everyone who just listens to the show: it's no small thing to me that there are thousands of people out there who listen whenever I post an episode. Thanks, Rustaceans! Happy new year, and until next time, happy coding! ================================================ FILE: docs/news/increasing-rusts-reach.md ================================================ ## Intro Hello, I'm Chris Krycho, and this is the New Rustacean podcast, a show about learning the Rust programming language. This is a News episode: Increasing Rust's Reach. ## Increasing Rust's Reach ### Background One of the major goals for the entire language this year is to expand Rust's reach, and increasingly the core team has recognized (even beyond the existing commitments in this direction) that we need to make the Rust community a more diverse and inclusive place. That includes things along many lines; one big piece is going out of our way to make sure we're easy to jump in for groups of people which have often been underrepresented in the programming world. Another is even just making it so our stuff is easier to dig into whether you're under-represented or *over*-represented in the technical world in terms of things like gender, ethnicity, and so on. As awesome as Rust is, there are many people for whom the barrier to entry is still too high to just up and jump in. It is *hard* for people if this is their first language especially. But it is also hard in some ways even just to see why you might use the language – the rust-lang.org landing page need some love. Or, as Jonathan Turner pointed out in our interview, you need a lot of knowledge about Rust to be able to use the documentation of the standard library. There are *lots* of those little paper cuts. ### The Initiative To make a real improvement in this category, the Rust team has kicked off an initiative called "Improving Rust's Reach." The goal is to lower its learning curve *by* drawing on the expertise of people who are outside the existing community, and that very well might mean *you* – whether because you're a member of those too-often-underrepresented groups, or because you're a designer or otherwise not the stereotypical picture of a low-level language hacker. The initiative is a set of small projects – driven by those same people who are outside the norm, but paired with existing Rust community leaders and empowered to tackle specific parts of the ecosystem to make it easier to get up to speed! There are there big benefits to participants: 1. You (someone who is *not* part of the main stream of current Rust users, in one way or another) get to dive in and learn a bunch about Rust from leaders in the Rust community while also making a significant contribution. That comes with, among other things, access to a private Slack team dedicated to coordinating this effort, with active feedback from . 2. You get to go to one of three Rust conferences of your choice later this year, on Mozilla's dime: - RustConf, August 18–19 in Portland, Oregon, in the US - RustFest, September 30–October 1 in Zurich, Switzerland - Rust Belt Rust, October 26–27 in Columbus, Ohio, in the US 3. You get some public recognition for all of your contributions! What does working on one of these projects entail? A commitment of 3–5 hours each week between August 7 and November 6—so, a three month commitment, with the expectation that you'll have a deliverable by the end. Depending on the project and your skill set, that deliverable might vary *widely*, of course: it might be anything from a series of pull requests to new tutorials in a given are. It might be Rust code, or it might be a mix of Rust and something totally different, like React JS. ### The Projects So, how can you get involved? Well, write a proposal for one of the projects! It’s due by July 18, so you should get on it in a hurry! You can see the full list in the announcement blog post, which I've linked in the show notes, but I thought it might be useful to include a short list of the initiatives. They are: 1. User Experience of Rust Documentation and Code Browsing Tools – Nick Cameron, core team contributor to rustdoc, rustfmt, RLS, and the compiler; and Steve Klabnik, core team docs guru and web tech enthusiast: help make it easier to use Rust's *documentation*, which will improve experience of using the standard library docs and the auto-generated docs that live at docs.rs. That needs web tech experience and an eye for design, because the docs have web front ends! 2. Adding Code Lints to the Clippy Developer Tool – Manish Goregaokar: add more and more helpful messages to Rust's main static analysis tool, including lints focused on helping people transition into Rust from other languages, tutorial-like messages, and more. 3. Improve the Approachability of the Design of rust-lang.org and/or crates.io – Aaron Turon: rust-lang.org and crates.io both need some work! The main page could use a lot more and better information on why you might want to use Rust, and crates.io could be both a lot nicer-looking and a lot easier to find your way around. If you have some design chops and some web skills, this is a place you could make a *big* difference for on boarding new users. 4. Improving the Video Tutorials at intorust.com – Niko Matsakis, one of Rust's core language developers and designers: video tutorials for Rust are still relatively rare, but they're a common way many people initially come up to speed on a new technology. You can help expand the actual video content as well as help evaluate it for what the current gaps are that might not be obvious to current Rust insiders. 5. Write Tutorials for Rocket and Diesel, Parts of Rust's Web Framework Story – Sean Griffin, creator of Diesel: we need people with experience in web development in web frameworks in the non-Rust world to help take this ecosystem from "barely bootstrapped" to "flying high." In particular, we need help putting together good teaching material—tutorials, videos, example applications, and improvements to the docs—that shows how to use Rocket, Diesel, and the two together to build real-world web applications. 6. Extending the Literate Programming Tool Tango – Felix Klock, a member of the Rust compiler and language teams: literate programming lets you write your code inline with text that describes it, so that documentation or planning and code can live side by side as a single living, working document. tango does that with Markdown and Rust, and making it more viable for the community as a whole would be a big win—and it might be particularly useful for Rust documentation: imagine if *all* Rust READMEs were in principle just "literate" Rust and you could run them! 7. Finding Missing Pieces in the Crates Ecosystem – Andrew Gallant ("burntsushi"), author of (among other things) the awesome *ripgrep*: Rust is still young, and its ecosystem of important libraries has real gaps. Andrew's idea is to build a small application in a language you're already comfortable with, and then Port it to Rust and use that experience to identify libraries present in the original language but missing in Rust. That turns into actionable knowledge for the Rust community as a whole: what crates need to be written for applications like that one? 8. Finding Missing Pieces in the Experience of Building a Command Line Interface (CLI) Program – Kamal Marhubi, maintainer of *nix*: Rust is already *decent* for writing small command line tools (as I've seen myself), but it could be *great* for it. If you're interested in building new CLIs or rewriting existing CLIs in Rust, this is the project for you. The main goal of this particular project is to identify the pain points in these kinds of projects today, and then smooth some of those rough edges out so it's easier for others to do build CLIs in the future! If you're noticing a theme there – lots of focus on documentation, and *some* on tooling – that's for a reason! Although things like teaching materials and visual design often get treated as a second-class part of any programming ecosystem (programmers tend to want to write code!), the reality is that poor design and missing or difficult-to-use documentation can and do dramatically *raise* the bar for entry into the ecosystem. A huge part of what people need therefore is not only the ongoing. And it's also the case that, while the Rust community values especially documentation already, we have a lot of work to do to make paths into the language for people who aren't already a lot like today's Rustaceans. So again: that's where you come in! Write a proposal and get it in by July 18! ## Outro Thanks, as always, to the show's sponsors! - Anthony Deschamps - Behnam Esfahbod - Christopher Giffard - Chris Palmer - Dan Abrams - Daniel Collin - Matt Rudder - Peter Tillemans - Philipp Keller - Raph Levien - and Vesa Khailavirta Thank you as well to everyone who shares the show with others, whether on social media, in the threads for the episode on Hacker News, Reddit, or the Rust user form, or by recommending in a podcast app! Show notes for this episode are at NewRustacean.com/show_notes/news/_3/. I'm on Twitter @chriskrycho; the show is @newrustacean; and you can always send an email to hello@newrustacean.com. A number of the shows coming down the line are listener-suggested – so yours could be next on the list! Until next time, happy coding! ================================================ FILE: docs/news/rust-1-20.md ================================================ # Rust 1.20 ## Intro Hello, my name is Chris Krycho, and this is the New Rustacean podcast – a show about learning the Rust programming language. This is a News episode, for Rust 1.20. ## Rust proper As the title of the episode suggests, Rust 1.20 came out today! That's a pretty amazing number if you take a step back and look at it. We've gotten used to this pace of releases in the Rust community, but it's still fabulous. In the last roughly 15 months, Rust has shipped 21 releases, starting with Rust 1.0, steadily improving the language and adding features without breaking backwards compatibility. In fact, if you go back and look at what Rust 1.0 looked like, you can see how it's both the same language as today's and yet a recognizably less mature language as well. Starting with this episode, I'll be putting out news episodes to coincide with each minor Rust release. Every six weeks seems like a reasonable amount of time to cover with as much as is going on in the Rust world---not least because there's more happening all the time! So, what's in Rust 1.20 itself? ### Associated constants The first big thing is the stabilization of *associated constants*. These are like other associated *items* that already exist, specifically associated *types* and associated *functions*. "Associated functions" are quite ordinary in Rust: they're just static functions that belong to a given trait, struct, or enum. Associated types are bit more complex: they're types – kind of like, but not the same as, a generic type – which are associated with a given trait, and which you must specify for any implementation fo that trait. (If that went a little over your head, don't worry: I have a planned episode to talk about them in detail in the future.) "Associated constants" are more like "associated functions": they're just constant items which can be attached to any trait, struct, or enum. In the case of a trait, you can define the constant item on the trait declaration itself, or on the `impl` block of a struct or enum. In the case of a trait, you can define the actual value, or you can leave it just a type and require the types which implement the trait to specify the value. And you can only use a trait constant with an actual implementation of the trait – you can not write a trait named `Foo` with a constant named `BAR` and then use it like `Foo::BAR`. But if you have a `Quux` which implements `Foo`, you *can* write `Quux::BAR` and it'll be what you expect. All of this might seem relatively arcane, but it's quite useful for a number of things. The Rust 1.20 announcement blog post points out that it lets you define quite a few things in e.g. an trait for floating point numbers simply as part of the *floating point type itself*, rather than having to have standalone constants in a floating point module. Moreover, this is one of several building blocks for more advanced, compile-time "metaprogramming" – or, as you might also describe it in this case, programming via the types themselves and at compile time, rather than only with the runtime behavior of the programming. This is a concept that we'll come back to on the show in the future because it's of considerable interest to me, and also because it's of considerable interest to the broader Rust community and development teams. ### Other bits Now, what about the other big things in Rust 1.20? Well, as with most Rust releases, there aren't a lot of big things! There are a bunch of small improvements and stabilizations in the standard library: as usual, these are just quality of life changes. But 20 releases worth of quality-of-life changes have added up quite a bit! A couple little tidbits that I thought were most interesting: the `unimplemented!()` macro now lets you specify *why* a function isn't implemented yet, so that when your program hits that point and dies, you can get an explanation printed to the console. Helpful when leaving notes for yourself! There are a couple handy new methods on the `Option` type, as well: `get_or_insert` and `get_or_insert_with`, which both supply mutable references to the item inside the `Option`, or insert a new one and get a mutable reference to *that* if the `Option` is `None`. Like I said: not game-changers, but the kinds of convenience methods that add up over time. There are a bunch of other changes like that, so I encourage you to take a look both at the release blog post and at the detailed change log for the release, both of which I've linked in the show notes. ## Community Now, for something old and new again in the show! In the early days of the podcast, I often called out ongoing community news bits, new resources, and so on in the opening minutes of each episode. I eventually realized, however, that that stuff would get out of date in a way that much of the tutorial-type material wouldn't, and dropped it. However, I want to keep the ability for the show to highlight a bunch of different things going on in the community, and these every-6-weekly-episodes are the new home for those kinds of things! ### Podcasts First up on that list, I'm delighted to say that this is once again *not the only podcast* in the Rust space! Back in mid-June, some other members of the community (the ringleaders seem to be Manish Goregaokar and Carol Nichols-or-Goulding, perhaps better known to you as "manishearth" and "carols-2-cents" where 2 is spelled in binary as 10) kicked off a new show called _Request for Explanation_. Every episode is a deep dive on some Rust RFC or another. If you want to hear about a specific RFC, or even to possibly be a guest on the show, you just file an issue on the GitHub repo where they're hosting the blog. You should listen! They're doing something *totally* different in the podcasting space than I am, and besides: more Rust podcasts is just more awesomeness as far as I'm concerned. ### Conferences As I release this, we're right in the middle of Rust conference season! - RustConf happened just a couple weeks ago, and videos will be coming out soon-ish. Last year the videos seem to have gone up about two months after the conference itself, and that seems to be about par for the course for other conferences I'm familiar with. But don't worry -- if you missed it, there are still a couple conferences you can get to! - RustFest is September 30--October 1 in Zürich, Switzerland. Tickets are still on sale, and the list of speakers is slowly being rolled out. I've never made it out there, but the attendees of the last few years have raved about it. The focus on Saturday is talks on everything from embedded hardware to testing and concurrency. On Sunday, the focus will be on learning and hack sessions! If you are in Europe, or Europe is easier for you to get to than the U.S., or you just feel like going to Europe would be awesome, you should get there! - Rust Belt Rust is October 26--27 in Columbus, Ohia, in the U.S. It's organized by Carol Nichols-or-Goulding, and includes a keynote by several people on the core team: Carol herself, Aaron Turon, and Niko Matsakis. The full schedule was announced today and includes a full day of workshops on Thursday and a full day of presentations on Friday. And---I'm *incredibly* excited about this---I'll be giving one of those talks on Friday! So if you'd like to meet up with me, that's the place and time! There'll be another news episode out between now and then, and I'll say it again. Related, I also hope (and will follow up with further info about) to have New Rustacean stickers available *at* the conference, and perhaps to make New Rustacean shirts available for purchase before then so we can be a whole troop of New Rustaceans. ### Meetups I also want to draw your attention to two meetups people asked me to mention! Both of them, sadly, I was unable to get this episode out in time for this month. One is a NYC Rust meetup; they have a meeting tonight, August 31, and will have more meetings in the future. I don't have a long-term schedule for that meetup, but you can follow up with the organizer, Robert Balicki for more details. The other one is the Triangle Rustaceans meetup, here in the Raleigh-Durham-Chapel Hill area in North Carolina. I've been delighted to attend two of the three meetings so far, and I'll be at one more, on September 25. That group meets on the fourth Monday of every month. If you live around here, or if you happen to be in the area then, you should definitely stop by! I'll be moving out of the area after that, but I also expect I *may* be helping start up a new meetup in the area I'm moving to (which, to my knowledge, doesn't have one yet). Don't worry: info about time and place for both of those is on meetup.com, and I'll have those in the show notes. ## Outro And that's everything I've got for today. If you'd like your stuff to land in the next News episode when Rust 1.21 comes out in six weeks, send it my way on twitter @newrustacean or @chriskrycho, or send me an email at hello@newrustacean.com. I'll be back in early September with a Crates You Should Know, looking at easy data parallelism in Rust with Rayon. Thanks to this month's $10-or-more sponsors: - Anthony Deschamps - Chris Palmer - Behnam Esfahbod - Dan Abrams - Daniel Collin - David W. Allen - Matt Rudder - Nathan Sculli - Nick Stevens - Peter Tillemans - Philipp Keller - Olaf Leidinger - Raph Levien - and Vesa Khailavirta As always, thanks as well to everyone who helps other people find the show---whether by just telling a friend, or by rating or reviewing it in iTunes or recommending it in another podcast directory, or by sharing it on social media! You can find show notes for this episode, including links to blog posts and conferences and meetups and more, at `newrustacean.com/show_notes/news/rust_1_20/`. Until next time, happy coding. ================================================ FILE: docs/news/rust-1-21-1-22.md ================================================ # News: Rust 1.21 and 1.22 Hello, I'm Chris Krycho, and this is New Rustacean, a show about the Rust programming language and the people who use it. This is a news episode about Rust 1.21 and 1.22. Listeners will notice that this has two releases in it and that I missed the 1.21 release. There's a good reason for that! I was moving across the country _and_ prepping for Rust Belt Rust, which was a _fabulous_ conference. If it happens again next year, you should definitely go: it was a really nice event, large enough to be interesting but small enough that you could meet many of the people there. And the micro-interviews I recorded there, which this will come out right in the middle of, were a blast---it was neat to see just how wide the range of attendees were, from one person I interviewed who had done no Rust at all before showing up to others who had been there since well before 1.0. And now, let's talk about news that has happened through the interval while Rust 1.21 and 1.22 came out! ## 1.21 Rust 1.21 came out on October 12, 2017. As is often the case, it wasn't an especially large release, and as usual that's no bad thing! 1.21 was essentially a "quality-of-life" improvement in a couple areas: * There are some places where locally-declared variables could be treated as `static` and _just work_ instead of being stack-allocated and therefore having local scope lifetimes... well, now they are treated as static and just work. This is one of the many small things that the Rust compiler team has done as part of this year's ergonomics initiatives that take things that intuitively seem like they _should_ be fine, and smarten up the language so they _are_ fine. * The standard library now includes the `for_each` method on the `Iterator` trait. For a long while, you've been able to do this via a crate, but it's super handy to have it present in the standard library. Often you just use a `for` loop, but sometimes, when you've chained a bunch of iterator calls together, and you want to do some effectual operation at the end of them, having a `.for_each` call at the end of that chain is _super_ handy. * 1.21 was the first release to support shipping the preview of the Rust Language Server via `rustup`. And the RLS is coming _soon_ to stable – Nick Cameron wrote [a blog post titled "When will the RLS be released?"](https://www.ncameron.org/blog/when-will-the-rls-be-released/) between the 1.21 and 1.22 releases indicating it should be in a non-preview, stable state by early 2018. I've linked that blog post in the show notes so you can get the details! * One other neat little library stabilization: you can now use the function `std::mem::discriminant` to be able to check the specific _discriminant_ of an `enum` type, which lets you compare whether two items are the same variant of enum, without bothering with the equality of the underlying data, and without needing to do a match expression. This isn't a _super_ common need, but even in my still relatively limited experience, it's something I've wanted! * Finally, Cargo got a nice little feature for supporting a pretty common use case: where you need to patch a particular feature, and it hasn't gotten upstreamed yet. You can just use the `[patch]` key in your Cargo.toml to override where to look up a given dependency. ## 1.22 Rust 1.22 was a nice Thanksgiving present, for those of us in the United States: it came out November 22 (_not_ on a Thursday, like normal, since that was the holiday). Like 1.21, this is a relatively small release, but the main quality-of-life feature in this one will make a pretty big difference in a _lot_ of the code we write. That feature is the first stable implementation of the `Try` trait for something besides `Result`. You might better know the `Try` trait as the trait which makes the `?` operator work as a quick-return for functions when you have a bunch of different `Result`s and want to quickly return `Err` cases and proceed only if you have an `Ok` case. Rust 1.22 stabilizes `impl Try for Option`, so you can now use `?` to do the same kind of immediate-return if you have a `None` and continue through the body of your function only if you have a `Some`. This bit of trait-based syntactic sugar helps a _ton_ when you have a function with an `Option` return type, and which has a number of places where it might return `None`. In the future, you'll actually be able to freely use it with a mix of both `Option` and `Result` return types, since `Result` and `Option` both implement the `Into` and `From` traits for each other. That's not there with 1.22... but it _is_ there on nightly! Coming Soon™️. One other important note about 1.22: you'll just get this automatically if you're using `rustup` (and for the most part, you should just be using `rustup`!), but there are _two_ 1.22 releases: 1.22.0, the normal release, and 1.22.1, which fixed a problem in Cargo with the latest version of macOS. `rustup update stable` will give you 1.22.1 automatically. ## Other news So that's Rust proper! But there are some other neat things going on around the ecosystem since Rust 1.20 came out, too. One fun thing I wanted to mention again after mentioning it in my special 50th episode is Rusty Spike: Jonathan Turner's weekly Rust news podcast. The episodes are roughly 3–7 minutes long, and Jonathan has settled into a really nice rhythm and routine with the episodes. It's a great show, and it covers things at a much more granular level than these New Rustacean news episodes do, so I think they end up being nicely complementary. I strongly encourage you to check it out! ### Rust conferences We've seen the end of the Rust conference season for the year, with the fall RustFest event in Zurich back at the end of September and, as I mentioned at the start of the episode, Rust Belt Rust at the end of October. The videos from RustFest are already up, so you can check those out. Videos from Rust Belt Rust are _not_ out yet, but keep your eyes on their YouTube channel – last year they came out a couple months after the conference, and that seems pretty common. In the meantime, if you want to see the content for _my_ talk at Rust Belt Rust, both the slides and the script are on my personal website. ### The `Failure` crate Since Rust came out, people have been iterating on the best ways to do error-handling in large projects. The `Result` type is really nice for making sure you have type-level control over the ways your errors are handled, but there are two downsides to using `Result`s throughout your codebase: 1. You can end up with a `Result` wrapping a _huge_ variety of error types as their own enum, to account for all the different types of errors that can crop up in your library or application while still having a single `Result` type you can use throughout. 2. Or you can end up with a bunch of different, much more specific `Result` error types, and then write a bunch of conversions between those error types for transitions between different parts of your library or application. Both of those involve a _lot_ of boilerplate. They work, and for all the reasons we've talked about before on the show they're very much preferable to exceptions. But it'd be nice to _not_ have to write so much of that boilerplate while still getting those benefits. For the first couple years of Rust 1.x, the go-to solution has been the Error Chain crate. As people used it in practice, a number of limitations and frustrations reared their heads—and so Rust contributor withoutboats recently released [the Failure crate](https://github.com/withoutboats/failure), which aims to improve on the design of Error Chain. I plan to dedicate a Crates You Should Know episode to `Failure` at some point relatively soon. It's an exciting development in the ergonomics initiative this year, and even if the crate is still pretty early in its development, it looks really nice. ### Wasm! Next up: WebAssembly! WebAssembly, or wasm, is a format for targeting _browsers_ with compiled code. Just last week, Alex Crichton [added early support](https://github.com/rust-lang/rust/pull/45905) for compiling to wasm directly from the Rust compiler. While you've been able to compile to wasm with Rust for a while, it's been a hairy process involving a tool called emscriptem, which was really designed for C and C++ toolchains, and specifically for things like porting games to the browser. Many (perhaps even most) places we'd want to use Rust don't _need_ all the extra runtime pieces that emscriptem supplied, so now we can ship zero-runtime Rust code straight into browsers using the Rust compiler itself. For someone like me, who writes TypeScript all day every day and would _love_ to be able to add Rust to my client-side toolbox, this is just incredibly exciting. I'll _definitely_ have a whole episode on this in the next few months. Note that this is very much _early_ support, and lots of things probably won't work. But it's a very important step. ### Some inbound changes with Rustdoc Last but not least, is something contributed by the community [via the RFC process](https://github.com/rust-lang/rfcs/pull/1990): [support for pulling in external Markdown documents as documentation for any given item](https://github.com/rust-lang/rust/pull/44781). The single most obvious win from this is reusing your README as the source for the docs for the crate itself. Up to now, if you wanted your README and your main crate docs to be the same, you had to manually copy it back and forth between the two. Now, on nightly (and hopefully it’ll land on stable in the next few releases), you can just mark any item with a doc include attribute pointing to the file location relative to the `src` directory, and it’ll pull that text in for you as documentation. So, for your README, you might add this line to the `lib.rs` item in the root of your crate: ```rs #![doc(include="../README.md")] ``` In other words, it's just a normal attribute with an argument! (If you need a refresher on attributes, you can go back and listen to episode 7, where I introduced them.) This is something I have wanted for _ages_, and I’m incredibly excited about it. Not least, because as a result, the script for this show and all future shows (and, soon, previous episodes too) _is attached_ to the show notes for the episode, on the `Transcript` struct! So to see it in practice, all you need to do is look at the source for this episode. I’ve had scripts for most episodes, but attaching them was a fair bit of manual work, and I just hadn’t made the time to do it—now I don’t have to! ## Outro And that's a wrap on _this_ news episode. The next news episode _should_ come out in about six weeks when Rust 1.23 comes out! In the meantime, I hope you enjoy the remaining Rust Belt Rust micro-interviews, and you can also look forward to three interviews with participants in the Increasing Rust's Reach program, which will be released throughout December. Thanks as always to this month's $10-or-more sponsors: * Aaron Turon * Alexander Payne * Anthony Deschamps * Chris Palmer * Behnam Esfahbod * Dan Abrams * Daniel Collin * David W. Allen * John Chandler * Matt Rudder * Nathan Sculli * Nick Stevens * Oluseyi Sonaiya * Peter Tillemans * Olaf Leidinger * Raph Levien * and Vesa Khailavirta If you're enjoying the show, please tell others about it so _they_ can learn about Rust. You can also support the show by recommending it in podcast directories like iTunes, or by sharing it on social media. You can find show notes for this episode, including the episode script, at newrustacean.com/show_notes/news/rust_1_21_1_22/. I'm on Twitter and GitHub @chriskrycho, and the show is @newrustacean on Twitter. You can also email me at hello@newrustacean.com. I've got a good stockpile of show ideas from people sending me requests that way; please keep it up. Until next time, happy coding! ================================================ FILE: docs/news/rust-1-23.md ================================================ # News: Rust 1.23 Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is a news episode for the Rust 1.23 release. ## Rust ### Rust 1.23 As with most Rust releases, there aren’t any huge features landing today! The highlights of the features that _are_ landing, though, are nice improvements. (I say almost the exact same thing every time I talk about upgrades—and that’s the way it should be. It’s _good_ that it’s rare for big features like MIR to land; that’s part of the stability story.) The most notable feature change here is to do with rustdoc: for most of 2017, the docs team has been working to move rustdoc over to use the `pulldown-cmark` crate, which tracks the CommonMark spec, instead of the prior hoedown C bindings crate. For the last many months, rustdoc on nightly has built both the `pulldown-cmark` version and the Hoedown-based version, compared them, and spit out the differences. Now, stable does the same—in preparation for the final switchover in some future release. A couple other little niceties in this release: * Two places where things unexpectedly didn’t work, or didn’t work the way you’d expect – `auto` traits in trait objects, and type-checking for some binary operations not playing out the way you might expect – now _do_ work. * The compiler now suggests you rename an import if it clashes with other imports. So if you import `MyModule::MyItem` and also import `SomeOtherModule::MyItem`, Rust will now helpfully suggest for the second that you do `import SomeOtherModule::MyItem as OtherMyItem` so that not only do you know what went wrong, you have some idea how to fix it. This is an especially nice change for _new_ Rustaceans: it’s compiler-as-teacher instead of compiler-as-antagonist. * Rust also displays errors correctly when there are either wide characters or zero-width characters in them. Yes, you heard that right: if you’re not familiar with either, suffice it to say there are printing characters which have _no_ width—modifiers for other characters, usually—and also printing characters with _extra_ width. In either of those circumstances, the beautiful error messages that get printed used to end up misaligned. Now they don’t! (Typography on computers is _really_ hard to consistently get right, it turns out.) There is also one nice optimization win in this release: the compiler [learned](https://github.com/rust-lang/rust/pull/45380) not to copy some function arguments when they’re rebound to local variables. This can decrease the memory usage in your code by 5–10%, which is no joke! And it turns out this optimization is one of the many wins that we’ve gotten out of the MIR feature—if you need a refresher on what that is, you can go back and take a look at [the first news episode](https://www.newrustacean.com/show_notes/news/_1/index.html), where I covered it in detail. The standard library saw a bunch of new `impl`s stabilized, as well as a few performance bumps. The [release notes](https://github.com/rust-lang/rust/blob/50989cd98dbef60b0b6f5baa0ce4203ce778adaa/RELEASES.md#version-1230-2018-01-04) have the details; most are sufficiently niche that you’ll be really happy if they do affect you but many of them won’t directly affect the _average_ you, as it were. ### The end of the first impl period That set of release notes was relatively quiet, which is unsurprising given the end-of-year holidays. But it also doesn’t capture just how much _was_ happening in that period, because a ton of it was features initially landing on nightly or even _starting_ the march toward stabilization, as the first impl period wrapped up! If you didn’t hear about the `impl` period, it was a concerned effort over the last quarter of 2017 to focus on _implementing_ all the ideas raised throughout the rest of the year. And it was a big success! Contributors all over the ecosystem collaborated to make _huge_ progress on the RFCs opened throughout the rest of the year and to help push a bunch libraries all the way forward to their 1.0 releases. (One of the most interesting things this included was the beginning of the marker for the next _epoch_ in Rust. If the idea of an “epoch” isn’t something you haven’t heard of, don’t worry: as we get closer to to 2019, when it will become much more important to understand, I’ll dedicate an episode to it.) Some of the highlights from the work in the language and compiler which caught my eye include: * the “non-lexical lifetimes” project, which will get rid of several pain points around the borrow-checker today, while also laying the foundation for more sophistication in the lifetime analysis in Rust in general * incremental compilation, which went through a number of design interations but is now on nightly and tracking toward stable! I’ll be talking about in a _lot_ of detail in the Rust 1.24 episode next month. * Getting support for the `?` short-circuit return operator in the `main` function (where you haven’t been able to use it historically because it didn’t match with the normal `main` return type). Besides that, there was a massive amount of effort that went into improving both Rust itself and the surrounding ecosystem. The “libs blitz” involved helping a _ton_ of Rust libraries get to 1.0 quality and indeed to ship their 1.0 versions, as part of the 2017 goal to improve the stability (actual and perceived) the library ecosystem. One of those is the [Diesel ORM](http://diesel.rs/), and you can look forward to hearing an interview about that with Sean Griffin in the next two weeks! In general, the first `impl` period seems to have been a rousing success, and I’m excited by all the progress the community made. I can’t wait to see how it goes in the next few years as we get better and better at it. ## Other goings-on in the community Since the last news episode, there have also been some big happenings in the Rust community at large. ### Firefox Quantum Perhaps the most interesting and “big” pieces of news since late November is that Firefox Quantum shipped. Quantum was a project to replace the entire style rendering engine in Firefox with the highly parallelized implementation built in Rust for Servo. This was a huge effort, but it seems to have paid off: Firefox’s performance got way better—and it really couldn’t have happened without Rust. As we’ll talk about in the upcoming Episode 22 on `Send` and `Sync`, and as I alluded to when we talked about the `Arc` type back in [episode 15](https://www.newrustacean.com/show_notes/e015/index.html "Not dumb pointers") Rust affords the ability to _know_ that you’re managing multithreaded tasks safely, and that’s something that’s essentially impossible to do in C++: even if you get it all right on the first pass in C++—which you might be able to do if you’re very skilled and a little lucky—_maintaining_ it will be nearly impossible. Mozilla had made two previous attempts at parallelizing the style rendering process, both in C++. They abandoned both, because they couldn’t do it safely and reliably enough. With Rust, they managed it successfully, and pretty quickly. It’s a huge success story, and is one of the first places for Mozilla itself that its bet on Rust over the last decade is paying off. As we say on [my _other_ podcast](http://www.winningslowly.org "Winning Slowly"): doing good work takes time! So props to Mozilla for doing good work with Rust, making a decade-long bet here that is now yielding dividends both for Mozilla and for a host of other people and companies. ### WebAssembly WebAssembly continues to gain traction in both small and big ways. On the small-and-fun side, I’ve seen several small but quite functional apps making their way around the internet written using Rust and WebAssembly—from an implementation of the [classic asteroids game](https://aochagavia.github.io/blog/rocket---a-rust-game-running-on-wasm/) to [a password generator](https://arkada38.github.io/2017/12/22/a-rust-password-generator-on-wasm/). At a slightly larger scale, there’s a _client-side_ web framework written in Rust, [Yew](https://github.com/DenisKolodin/yew), which leans heavily on ideas from Elm and React—you get the equivalent of [JSX](https://reactjs.org/docs/introducing-jsx.html), just by using Rust’s macro system—and compiles to WebAssembly, using the [stdweb](https://github.com/koute/stdweb) crate to do the small amount of DOM interaction required. It’s young, of course, but it’s quite impressive and I’m really excited for what it heralds. There’s also—and this is _super_ exciting to me personally because of my day job—a [spike](https://github.com/glimmerjs/glimmer-vm/pull/752) of the Glimmer rendering engine used in Ember.js implemented in Rust and WebAssembly. There’s a very good chance that I’ll be shipping Rust to production in 2018 as a result: not because _I’ll_ be writing Rust myself for work (though boy do I want to!) but because our app will be shipping it as part of the framework code. And that’s really the perfect place for WebAssembly—though in a tech talk I gave at work a few weeks ago, I noted a few other places we might conceivably use it in the future. Here’s hoping, right? Summing all of that up, there’s a great blog post by Michael Gatozzi called [Rust and the Case for WebAssembly in 2018](https://mgattozzi.com/rust-wasm), where he makes the case that Rust is well-positioned to become the primary language for targeting WebAssembly, because of the same combination of safety and approachability that makes it so attractive to people who were formerly put off by systems programming more generally. I’ve linked that post; you should definitely give it a read! ### 2018 In 2017, the Rust core team used the RFC process to establish goals for the year, and they paid off pretty handsomely. So for 2018, they’re repeating that same approach, but with a new wrinkle: in addition to the RFCs defining the roadmap for the year, they’re soliciting input via blog posts. You can [check out the announcement at blog.rust-lang.org](https://blog.rust-lang.org/2018/01/03/new-years-rust-a-call-for-community-blogposts.html "New Year’s Rust: A Call for Community Blogposts"), but the short version is: the core team recognizes that writing RFCs is _hard_; writing a blog post has a lower bar for entry, and may also be more accessible to other readers in some ways. To quote: > These can take many forms: > > * A post on your personal or company blog > * A Medium post > * A GitHub gist > * Or any other online writing platform you prefer. > > We’re looking for posts on many topics: > > * Ideas for community programs > * Language features > * Documentation improvements > * Ecosystem needs > * Tooling enhancements > * Or anything else Rust related you hope for in 2018 They point to several example posts out there, one of which was Michael Gatozzi’s post on WebAssembly I mentioned just a minute ago! If you have ideas or vision, write it up and link to it on the relevant threads—you can help shape the direction Rust goes in the year ahead! ## Outro And that’s a wrap—but that’s plenty! * Aaron Turon * Alexander Payne * Anthony Deschamps * Chris Palmer * Christopher Giffard * Behnam Esfahbod * Dan Abrams * Daniel Collin * David W. Allen * John Rudnick * Matt Rudder * Nathan Sculli * Nick Stevens * Peter Tillemans * Olaf Leidinger * Oluseyi Sonaiya * Raph Levien * and Vesa Khailavirta If you're enjoying the show, please let others know about it in person or on social media, rate and review in your favorite podcast directory, or, if you're feeling extra generous, by sending some financial support for the show my way at Patreon.com/newrustacean or as a one-off via any of a number of other services I've listed on the show website: newrustacean.com. NewRustacean.com also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/news/rust-1-24.md ================================================ # Rust 1.24 Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is a news episode for Rust 1.24. ## Rust Release With apologies for this being over a week late—I’ve been first sick and then swamped by work!—let’s dive right in! It’s mostly the usual with this release: lots of small changes and wins. There’s one _really_ big win landing, but first, a few highlights from the smaller pieces: * The Rust compiler now defaults to doing builds with 16 parallel codegen units for release builds. This means that it splits up the LLVM code generation process into 16 pieces and runs them in parallel to whatever extent it can. The upside of this is that build times can be significantly faster, because the LLVM code generation is something like _half_ of the work that the Rust compiler does. The downside is that the compiled executable can be slightly slower, because LLVM doesn’t have quite as much insight into the whole codebase and therefore into some of the optimizations that might be available. Since there’s a tradeoff here, this is also a configurable option: you can set the number of codegen units to 1 when doing a build and wait the extra time for the build to finish in exchange for the absolute fastest executable on the other end… or you can trade a little bit of runtime performance for faster rebuild cycles. * Speaking of performance: the `str::find::` function got an improvement under the hood that should speed up any use of it by a factor of 10 in most scenarios. Yes, 10x faster! Now, about that _big win_: as of this release, Cargo defaults to using incremental compilation by default for all non-release builds. _Incremental compilation_ means that Rust no longer needs to rebuild every part of your crate just because you added a `println!()` in one module: it only recompiles the things it actually _needs_ to. It does this by storing the results of its previous builds in a _cache_, and then leaning on that wherever possible. Work on this is far from done, but this is a huge step in improving the experience of working with Rust on a day-to-day basis. In terms of the real-world impact: when you’re using incremental compilation, your _first_ build will as often as not be slower, because it has to create those cache artifacts for use in later builds. However, _after_ that, you can expect to see fairly dramatic decreases in compile times compared to a non-incremental rebuild (a.k.a. what we’ve all had for years now)—compiles might take anywhere from half as long all the way down to a tenth or a fifth as long. And this remains a big focus, so you can expect to see this continue to improve! Note, again, that this is only enabled for _development_, i.e. non-release builds. For release builds, you want to throw everything at it in the smartest way possible, and that means turning off incremental compilation to give LLVM all those passes it needs with the whole compile artifact together. The net of all of these changes but _especially_ incremental compilation is that stable Rust should just be dramatically nicer to work with in terms of compile times now. ## 2018 Roadmap RFC The weeks since the last Rust release have also seen a concerted effort to sort out the game plan for this year’s development cycle. As I noted in the previous news episode, the core team took a different tack this year than previous years, soliciting input not only via the normal RFC process but through blog posts. That proved to be a _smashing_ success: there were something like a hundred blog posts that were part of the conversation! Aaron Turon did the work to read through _all_ of them and synthesized them into a draft of the RFC for the 2018 Roadmap, and then got further input on the text of that. The result is a nice, tight story that particularly picks up on a theme from a bunch of the different blog posts that circulated: basically, making 2018 a continuation of the late-2017 `impl` period, and _finishing_ a lot of the things we already have in flight. The major _goals_ for 2018 are going to be: * Ship an epoch release: Rust 2018 * Build resources for intermediate Rustaceans * Connect and empower Rust’s global community * Grow Rust’s teams and new leaders within them Those are pretty high-level, so at the more on-the-ground level, the Rust community is going after these by targeting specific domains: * Web services * WebAssembly * CLI apps * Embedded devices These are not the _only_ things going, of course, but they represent the _core_ of the work for this year. Others, including further work on language features that are already in nightly, tooling improvements like continuing to push _hard_ on build times, and so on, are also part of this overall roadmap. So much so that compile times are explicitly called out in the full text of the RFC, for example, even though they’re not one of those areas-of-focus! ## “Rust 2018” Now, one other major point discussed by the RFC, and which we should talk about in some detail, is the concept of a Rust “epoch.” This is part of Rust’s still-developing strategy for _stability without stagnation._ We’ve gone through almost 3 years of completely backwards-compatible releases now – 25 releases since 1.0! – and the language has evolved an astounding amount over that time. Rust 2018 marks not a departure but a thoughtful continuation of this theme. It’s an _epoch_ – ‘e’ ‘p’ ‘o’ ‘c’ ‘h’, an era in history – and marks the start of the next chapter for Rust. And Rust 2018 really represents two distinct (though related) things: a _technical_ step, and a _marketing_ step (and the two go together). Let’s talk through what the epoch means in that order: technical, then marketing. ### Technical Technically-speaking, a Rust epoch has two major things going for it: 1. The possibility for a backwards-compatible breaking change. Yes, you heard that right, and I’ll explain in a moment. 2. The ability to bring together the whole ecosystem into a kind of “technical coherence.” #### Backwards-compatible breaking changes So: backwards-compatible breaking changes. That sounds… impossible. Let’s start with the motivation, though. One thing that everyone generally recognizes is desirable is the ability to use the lessons learned as you develop a language to continue to improve language design. There are significant problems with permanent backwards-compatibility: ask C or JavaScript! There are parts of the language that (a) effectively no one uses and (b) effectively everyone wishes no longer existed. However, neither language (and especially JavaScript) wants to introduce breaking changes, and for good reason. Code written decades ago still needs to work! On the web, especially, that’s one of the fundamental commitments that all the standards bodies and browser vendors _mostly_ share (at least as concerns JavaScript): _don’t break backwards compatibility._ Over time, though, this leaves you painted into corners by language design decisions made many years ago that you cannot undo—even when a decade of using those features leaves you convinced they were a bad idea! But there are also _really_ serious potential problems for making breaking changes to a language. Just ask Python: it’s been a decade since Python 3 came out and the community-wide transition from Python 2 _still_ isn’t over. The transition path, for a huge amount of that time, simply wasn’t smooth enough. It was enormously costly for anyone to convert their library to Python 3, and it was very difficult (especially early on) to ship python libraries that worked with both versions. So we’re caught on the horns of a dilemma, it seems. Maintain backwards compatibility, even when you see opportunities for really significant improvement, so as not to break your users or split the community—or make a breaking change, which most people agree _does_ improve the language but which imposes major costs for transition and effectively splits the community. We _think_, as a Rust community, that we have a third way. We can introduce an _epoch_, which is a marker for a set of _parsing-level_ breaking changes, and set a flag on a per-project basis that tells the Rust compiler “Parse and compile this crate with _these_ rules.” At the same time, the Rust compiler will maintain support for all _previous_ epoch’s parse modes. And the compiled output between all epochs will remain compatible with each other. In practical terms, that means that we can introduce new keywords, stop treating certain old keywords as keywords, and even make tweaks to make certain kinds of other declarations valid which weren’t before and vice versa. But the compiled output of whatever tweaks we make for Rust 2018 will work alongside compiled output from what we might retroactively call the Rust 2015 epoch. So Rust you wrote in a crate that you felt was “finished” back in 2015, on Rust 1.2 or something, can be a dependency of Rust 2018 code. Even more interestingly, if you wanted to go back and update that—perhaps because it was using a long pre-1.0 version of the Serde serialization and deserialization crate—you could continue to write Rust 2015-style code, while updating to use a version of Serde that was written in Rust 2018. In other words, we get to make small, carefully considered, breaking changes to the surface syntax of the language _without breaking backwards compatibility_. This is Rust’s “stability without stagnation” mantra taken to a whole new level. This doesn’t cover _every_ kind of backwards-incompatible change you ever might want to make to a language, of course. Deep changes to semantics still aren’t viable. If Rust (for some unfathomable reason) wanted to throw away its core notion of ownership and the borrow-checker and everything else, well… that would be the kind of breakage this kind of thing would not and could not solve. But for the kinds of ergonomic improvements and tweaks that are now fairly obviously desirable based on the community-wide developments that have happened since Rust 1.0 came out… we can solve those! #### Synchronizing the ecosystem The other piece of this is the opportunity to bring the ecosystem back into a degree of synchrony. The last three years have seen enormous exploration and growth in both the broader Rust ecosystem and in Rust itself. There has been nearly constant change in the language – and while that’s amazing, it also means that it’s easy for different pieces of the ecosystem to be moving at different speeds. Keeping all of the documentation in sync with the language and standard library, for example, is the kind of thing that’s hard to manage just in terms of technical accuracy. It’s even harder to make sure that everything stays up to date in terms of what is idiomatic. An epoch gives us a chance to _focus_ on that kind of whole-ecosystem coherence. The push up to Rust 1.0 had a lot of that kind of focus: it was important to present a unified and interesting story about what Rust had to offer now that it had reached a point of _stability_, and to make it as easy as possible for someone coming in to check it out now that it had hit 1.0 to say “Oh, here are how the pieces fit together.” The goal is something of a repeating process of _intentional_ fragmentation and experimentation followed by coming back together with the shared solutions and results of that fragmentation and experimentation into a coherent whole. That dynamic can be incredibly powerful. We’ve already seen some of the fruit of that in the 2017 `impl` period, and 2018 is shaping up to be a whole year of focus that way. I think it’s going to yield huge dividends. Among other things, it means landing all those efforts the Rust 2018 Roadmap RFC outlined. It also means polishing up a new version of Rust’s documentation tooling, and landing solid 1.0 versions of rustfmt, improving the reliability and usefulness of the Rust Language Server, and bringing all the documentation up to date (hopefully including the reference!). ### Marketing The idea of an “epoch” also lets us _use_ all that technical-and-ecosystem coherence to help “sell” Rust. There are lots of people out there who’ve looked at Rust and decided it was too immature for—and in many cases that was a perfectly reasonable decision! But Rust has changed a _lot_ in the last few years—from the availability of stable libraries in the ecosystem at large, to the ease of using learning and using the language itself, to the quality and usability of tooling in editors, and so on. It’s useful in driving adoption to _let people know about that_! So the other thing Rust 2018 does is give us a place to showcase all those improvements, across a bunch of different fronts. That goes for all sorts of things. One of those I’ve been looking forward to the longest is bringing a unified and coherent design language to all the Rust web properties, and using that design language for a revamped and more useful Rust landing page with better explanations of how to use Rust, how to get involved in the community, and so on. And as we land the Rust 2018 epoch—probably with Rust 1.29, in early fall—we will have a coherent story to tell people about the value proposition of Rust and why they might look at it again if they looked at it once before. ## Outro So that’s a look at what’s coming in Rust in 2018! Thanks as always to this month’s sponsors—you’re all awesome, and I appreciate you. The sponsors who contributed at least $10 were: ### Sponsors Thanks, as always, to all of this month's sponsors. Contributors who gave at least $10 included: * Aaron Turon * Alexander Payne * Anthony Deschamps * Chris Palmer * Behnam Esfahbod * Dan Abrams * Daniel Collin * David W. Allen * Hans Fjällemark * John Rudnick * Matt Rudder * Nathan Sculli * Nick Stevens * Peter Tillemans * Olaf Leidinger * Oluseyi Sonaiya * Raph Levien * Vesa Khailavirta * and Zachary Snyder If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for _this_ episode at . If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/news/rust-1-25.md ================================================ # News: Rust 1.25 Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is a news episode for Rust 1.25. Already! ## Follow-up First things first: some follow-up from the *last* news episode. Between when I recorded that and now, the language we’re using for the “backwards-compatible breaking changes” I discussed then has changed. Instead of “epoch” (or “epoch”) the Rust core team decided to go with “edition.” For one thing, there’s a consistent pronunciation of it! For another, and more importantly, “edition” is a word that far more people understand, and it communicates the right things to people for whom English isn’t their native language. That’s a big deal, and it’s an *especially* big deal when one of the goals for Rust in 2018 is broadening Rust’s international and multicultural reach! “Edition” also gets the idea across more to other communities: it’s more reminiscent in the *right* ways of things like the C++2011 standard. ## Rust 1.25 With that important bit of follow-up out of the way, we can dive in and talk about what’s going on with Rust 1.25! ### Rust proper One major stabilization for this release is [RFC 1358](https://github.com/rust-lang/rfcs/pull/1358), for `#repr[align(x)]` – which lets you specify the specific number of bytes to use for aligning a given item. This is an important tweak for people writing code that needs to meet specific hardware requirements, or that needs to interoperate with specific compiler output from the GCC or MSVC C and C++ compilers. Most of the time you don’t need this *at all*: the compiler just figures out a good way to lay out the data for you. When you *do* need it, you’ve been able to do this manually for a long time. This feature stabilizing lets you get it for a lot less manual work, though: you can just use an attribute to tell the compiler “Hey, lay this out with this byte alignment instead of whatever you’d normally use,” and trust that the compiler will get it right – no more manual work required for those scenarios. That’s pretty neat! It’s also been a long time coming; the RFC was opened in November 2015, and approved in May 2016. That’s over two years! Slow and steady wins the race! Two other language features I’ve wanted for a *long time* also landed in this release. Both of them are just little syntactical niceties, but *boy* are they nice. The first one is that you can now do *nested* path imports, using the curly brace syntax. (I’ve thrown a small example of this in the show notes, so you can see what I mean.) This makes for a much nicer experience when you’re importing a bunch of things from different sub-modules of a given crate. And I believe the rustfmt formatting tool already has smarts in place to handle this so that you can get nicely laid out, easy-to-read nested imports as well. Another syntactical nicety is that Rust now lets you write leading `|` characters for *each* of the items listed in a given pattern match. I have mixed feelings on this one: in other languages where that’s the case, the leading `|` is what delineates the pattern match. Here, it’s just the separator between multiple terms that all have the same result. However, the option is there so that when you have enough, or complicated enough, items that you have to span multiple lines, you can visually line them up. I’ve dropped a code sample in the show notes for this episode to show why this actually ends up being *less* clear – again, it’s a function of how Rust matches are *different* from the other languages that support this. But it’s there if you want it! Finally, an old, long-deprecated (and always unstable) attribute for using SIMD has been removed. If you’re a big fan of SIMD, though, don’t worry, because this got removed because we’re getting full SIMD support on stable pretty soon – hopefully in time for the Rust 2018 edition! Some of you are giddy about this; others of you are saying “I know that acronym, I think?”; and others are saying “What in the world is SIMD?” So, a quick overview: the acronym stands for “single instruction, multiple data,” and it’s a way of taking a bunch of different data and running the same instruction on all of them. In the concurrency-vs.-parallelism discussion, this is a kind of *parallelism*: there’s only one *instruction* happening, but’s happening on multiple pieces of data at the same time. SIMD in practice is a set of instructions available on modern compilers that are powerful when you need to apply the same transformation to a *lot* of data. One canonical example is applying the same volume adjustment transform to a bunch of audio samples – because you want to turn this podcast up, for example. You can check out [RFC #2325](https://github.com/rust-lang/rfcs/pull/2325) for discussion of how that stabilization process will go – starting with x86 SIMD instructions, but with the foundation in place to add other platforms and indeed to be portable. This could be a huge win for Rust in performance-critical spaces. One other sort of “behind-the-scenes” note – this update also included getting Rust using LLVM 6.0.0 – LLVM, if you’re unfamiliar, is the compiler backend for Rust (along with tons of other languages including C, C++, Objective-C, Swift, and many more). This is more than just a nice “keeping up with changes upstream” thing, though that in and of itself is important. It’s also important for fixing bugs around the same SIMD instructions we just talked about, and for using the LLVM WebAssembly back end! ### Cargo Cargo also got a bit of love this release. One of the more notable changes you might see day-to-day is that when you run `cargo new`, it defaults to generating a binary for you instead of a library. (You can of course still run `cargo new --lib` to get a library.) The thinking here is that we want the first run experience for new users to be as smooth as possible. Experienced users know how to type those couple extra characters to generate a stub for a library, but it’s extra mental work for someone just trying out the language for the first time. After all: what’s the first thing *most* people do when they go to use a new language? Build a small program! Whether that’s hello world or a small command-line tool or something like that, people don’t generally *start* by writing a library, but with small programs. This optimizes for that case, just to make the on-ramp a little smoother. ## Community Goings-On Of course, there have been a bunch of things happening in the community since the last news episode as well. - Matthias Endler (who you may remember I interviewed at Rust Belt Rust last year) launched [Hello Rust](https://hello-rust.show)—a video series Matthias describes as “a lighthearted live-programming channel about my journey to become a fearless, more effective Rust programmer.” I’m *extremely* excited to see this out there, as video content is a really helpful way to help people learn the language that we don’t have much of yet! - Speaking of learning materials: there’s a new Rust book… in Portuguese! The title (translated) is [“Functional and Concurrent Programming in Rust”](https://www.casadocodigo.com.br/pages/sumario-rust-funcional-concorrente) – and I admit to being a little jealous that our Portuguese Rustaceans have a book focused on that topic, as it sounds awesome! - There’s a neat new load-testing tool you can use with your web applications (Rust or otherwise!) called [drill](https://github.com/fcsonline/drill) – it’s designed to be lighter weight (and maybe faster, too) than many of the existing load-testing solutions out there. If you have a web application in *any* stack and need to see how it behaves under load, you might give drill a look. - There was also a really fun bit of news announced at EmberConf a couple weeks ago: Rust is also being used to reimplement the VM that runs the Glimmer rendering engine used in Ember.js and Glimmer.js. Yehuda Katz and Alex Crichton have been hammering away at this since last December or so and I’ve mentioned it on the show before, but the fun bit is that *it’s working*. You can actually see the app running with it at schedule-wasm.emberconf.com in any non-Safari browser. (Safari accidentally, and temporarily, broke wasm with its fix for the Spectre and Meltdown vulnerabilities; but it’ll be back soon.) - Next up – and this one is perhaps my favorite of all of these (though it’s a close competition with the Glimmer bits): I heard last week from a listener in Russia who was inspired by the show, and particularly by the bonus episode with my “Becoming a Contributor” talk, to start collaborating with other Russian Rust users to translate the second edition of the Rust book! How great is that? - Finally, the RustConf [call for proposals](https://cfp.rustconf.com) is open, and will be until April 13! And I’m on the program committee, so I’ll be reviewing your proposals and coordinating with the rest of the team to decide which talks we’ll be hearing – and I’ll see you there if you’re going in August! ## Closing That’s a wrap on Rust 1.25. There was a fair bit going on, but just wait till 1.26! The amount of stuff stabilizing this year is going to be pretty crazy, and pretty great. I also expect to have two deep dive episodes on Traits over the next three weeks! 1.25 just… snuck up on me. March was crazy! Thanks to this month’s $10-or-more sponsors: - Aaron Turon - Alexander Payne - Anthony Deschamps - Chris Palmer - Behnam Esfahbod - Dan Abrams - Daniel Collin - David W. Allen - Derek Buckley - Hans Fjällemark - John Rudnick - Matt Rudder - Nathan Sculli - Nick Stevens - Peter Tillemans - Paul Naranja - Olaf Leidinger - Oluseyi Sonaiya - Ramon Buckley - Raph Levien - Vesa Khailavirta - and Zachary Snyder If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for _this_ episode at . If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/news/rust-1-26.md ================================================ # Rust 1.26 Hello, I’m Chris Krycho and this is New Rustacean, a show about the Rust Programming Language and the people who use it. This is a news episode for Rust 1.26. This is, it turns out, one of the biggest single point releases in Rust’s history—a lot dropped in this release! So let’s dig in. ## Language stabilizations The biggest set of changes is in the language itself. There are, by my count, *five* major stabilizations in the core language this release. (And there’d have been one more, but it ended up being rolled back because the beta release found some bugs in it!) ### `impl Trait` First up is the biggest, and what will I think prove to be one of the most important changes to Rust since 1.0: the `impl Trait` feature landing. I’m going to keep my summary of this brief, because a *large* chunk of the next teaching episode – which should be out next weekend – will focus on all the nitty gritty details. The *very* short version is that where historically if you wanted the return type from a function to be a trait instead of a concrete type, you had to wrap it in a pointer. Most typically, you’d see something like `-> Box>`, for the case where what you cared about was not the concrete iterator type but that it was an iterator. This meant two important things: 1. You always had heap allocations, whether or not you actually needed them for any reason *other* than that the type being returned was a trait. Thus the `Box` (or other similar heap-allocated pointer). 2. You always had dynamic dispatch rather than static dispatch (as you have in most other cases, including generics). `impl Trait` eliminates *both* of those. You can now write – both in function argument position and in return position – `impl Iterator`. Note that there *are* times when you need a pointer and dynamic dispatch still: whenever you’re returning *different* iterator types from the same function. But for the simple cases, you can now get static dispatch with monomorphization, get rid of the heap pointer, and get much nicer type mismatch errors to boot! Again, we’ll talk about this a bunch more in a week or so when I get the second part of our traits deep dive episode out. ### `match` improvements #### dereferences The next major change to the language – which is *also* a contender for biggest-change-since-1.0! – is new match behavior around dereferences. Historically, when writing a match against a reference, you had to write something like this (assuming a reference to an `Option` type): ```rust,ignore match optional_name { &Some(ref name) => println!("Hello, {}!", name), &None => println!("Hello, somebody!"), } ``` If you missed any part of that – the `&` reference operator before `Some` or `None` or the `ref` before `name` inside the `Some` pattern match – the Rust compiler would tell you *exactly* what to write to make it type-check... but you still had to fill it in yourself. This is more than a papercut; and it shows up constantly in idiomatic Rust, where references are all over the place. Rust 1.26 changes all of that. Precisely because the compiler *can* figure out exactly what you need here, it now does. It knows you’re matching against references to the enum variants, and it knows that you’re getting a reference to the contents – so now it does that automatically. From 1.26 forward, you’ll write it the way you probably expected to in the first place: ```rust,ignore match optional_name { Some(name) => println!("Hello, {}!", name), None => println!("Hello, somebody!"), } ``` The types (including lifetimes and borrow analysis) are all still exactly what they were before; there’s no lost safety here. It’s just less work for you to do when the compiler already knew exactly what to do! #### Fixed-entry slice patterns The other match-related feature that landed in 1.26 is “fixed-entry slice patterns”. This is for the case where you want to pattern-match against a slice, and there are specific scenarios you want to handle. For example, let’s say you wanted to match on an array of numbers and do one thing if it started with 1 and something else otherwise, you can do that now. ### `main` can return `Result`s now Next up: one of the pain points most people run into early in Rust is with error handling. Nearly anywhere in Rust, you can return a `Result` type, and use the `?` operator to essentially “short-circuit” and just return an error case early. This lets you basically write your local code in a function on the happy path, while still explicitly opting into returning early for error codes. But not in `main`. Until 1.26, `main` always had to return the unit type. As of 1.26, though, `main` can return a `Result`. The only requirements are: - The `Ok` type must be `()` - The `Err` type must implement `Debug` – so that it can be printed. This eliminates the speed bump for new programmers, of course, but it also means that the rest of us don’t need to have our `main` just call a `run` function which happens to return a `Result` that we ourselves debug print and quit. ### Other new syntax There are a couple other nice syntax stabilizations as well. One is inclusive range syntax. We’ve had *exclusive* range syntax for a while: `0..10` would give you 0 through 9 and exclude 10. If you want to include the range “0 to 10, including *both* 0 and 10”, you can now write `0..=10`. Finally, you can explicitly write `'_` in places where lifetime annotations would normally be elided. I’ll refer you to the [original RFC, #2115](https://github.com/rust-lang/rfcs/blob/master/text/2115-argument-lifetimes.md), for the details here as it’s a pretty nuanced discussion (and a really great RFC!). The new syntax here is just letting us use `_` in lifetimes the same way we can in other contexts in the language already: “we don’t need to name this particular type or value, but we want a placeholder for it.” The kinds of spots you’ll drop this in are where you want to make it explicit that a borrow is happening – for example in a return type where a borrow *could* be elided, but it’s helpful to *show* that it’s happening, but you don’t care about what the “name” of that borrow scope is. ## Standard library stabilizations There are some really nice additions to the standard library. I’m only touching on a couple of them – specifically, the ones that caught my eye. First up, the `fs` modules now has a number of really nice convenience methods, each of which let you do fewer module imports *and* skip intermediate allocations: - `fs::read` reads the whole contents of a file to a buffer of bytes - `fs::read_to_string` does the same but as a string instead of a buffer - `fs::write` writes a buffer of bytes directly to a file Previously, you had to open both the `fs::File` and the `std::io::Read` or `std::io::Write` modules, and then open or create the file prior to writing it. That wasn’t *terrible*, but it’s a lot nicer to just be able to do `let contents = fs::read_to_string(path_to_a_file);` instead. There’s also a nice new method on the `hash_map::Entry` type: `and_modify`. This lets you update an existing entry if it exists before inserting a new element if it doesn’t. Again: you *could* do this before, but you usually need intermediate terms and/or longer ways of writing it out. Last of the ones I want to call out is one of those little things that is super surprising we didn’t *already* have it, actually: `process::id` is a simple function get the OS-assigned process ID associated with the process where you call the function. The [release notes](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1260-2018-05-10) have all of the rest, so take a look! ## Community On the community front, there are a *bunch* of neat things in motion, and I certainly can’t keep up with them all. In fact, your *best* bet… is to listen to a different podcast! I’ve mentioned it before, but wanted to call your attention again to the Rusty Spike, which is a *weekly* update of all the major things going in the Rust ecosystem, from Jonathan Turner, who I interviewed last year. There were a trio of big, related releases this week: the `regex`, `csv`, and `docopt` crates all hit 1.0! These are, to varying degrees, pretty core to the Rust ecosystem. `regex` in particular is used *everywhere*. The `csv` and `docopt` crates are both quite a bit more specialized, but even so it’s really neat to see them hit 1.0 with the associated commitment to stability. Each of them has been pretty stable for quite some time *anyway*, but pushing things across the finish line like this is an important part of the our story of a *stable* language and ecosystem. And that’s extremely important as we aim to drive increased Rust adoption. In the WebAssembly world – that beautiful world where I’m actually getting to write Rust a tiny bit for some open source work I’m doing! – there has been a *lot* going on since Rust 1.25 came out. One of the biggest, neatest bits is that there’s an online IDE targeting WebAssembly specifically: [WebAssembly Studio](https://webassembly.studio/). It’s still pretty early, but it’s also pretty neat. There’s also a really neat tool called `wasm-pack` which lets you take wasm code generated via the `wasm-bindgen` tool and ship it directly to npm for straightforward consumption from other JavaScript. It’s hard to overstate how big a deal this is: the barrier for shipping wasm in the Node world – and, given how much the front end world uses npm, *also* to browsers! – just got way, way, way lower. As someone who is both a massive Rust fanboy *and* a front-end developer, I could not be giddier about this. And in a happy turn, the open source work I’ve just started will get to lean *hard* on this directly. There are also a few new Rust subteams that have spun up or kicked into high gear since the start of the year, but which I haven’t mentioned previously. There are now working groups for compiler performance, networking tools, command line tools, wasm, and codegen – and that’s just the ones I can dig up or remember! Also, with apologies for announcing this much later than I meant to, I wanted to note a neat Visual Studio Code plugin from long-time listener Marcin: “Search crates.io”. Once you’ve installed it, if you’re in your `Cargo.toml` file, you can start typing crate names and it’ll do a lookup against the crates.io registry and give you a list of crates and versions. It’s still a bit rough, and doesn’t always do exactly what I want, but it’s a great step in the right direction and I recommend you test it out and give Marcin feedback on improving it. Ultimately, I’d like to see this kind of functionality make its way upstream into the RLS so we can have this functionality everywhere. ## Closing That’s definitely not everything that has been going on, but it’s as much as we can cover today! It somehow seems fitting to me that this release, pretty much at the 3-year mark since Rust 1.0, was such a huge deal. And there’s still more coming this year. So, as I said last time: buckle up! Thanks to everyone who sponsors the show. This month’s $10-or-more sponsors included: - Aaron Turon - Alexander Payne - Anthony Deschamps - Chris Palmer - Behnam Esfahbod - Dan Abrams - Daniel Collin - David W. Allen - Derek Buckley - Hans Fjällemark - John Rudnick - Matt Rudder - Marshall Clyburn - Nathan Sculli - Nick Stevens - Peter Tillemans - Paul Naranja - Olaf Leidinger - Oluseyi Sonaiya - Ramon Buckland - Raph Levien - Vesa Khailavirta - and Zachary Snyder If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for *this* episode at . If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/news/rust-1-27.md ================================================ # Rust 1.27 Hello, I’m Chris Krycho and this is New Rustacean, a show about the Rust Programming Language and the people who use it. This is a news episode for Rust 1.27. ## Rust 1.27 Rust 1.27 is another big release – if not quite as big as 1.26 was, still very significant. ### Language stabilizations Let’s start by digging into the stabilizations for the language itself. #### SIMD The first big new stable feature is one I already discussed briefly in [the news episode for Rust 1.25](https://newrustacean.com/show_notes/news/rust_1_25/): SIMD coming to stable Rust. Back in Rust 1.25, the old feature flags were deprecated, in preparation for stable SIMD landing – and the first step of that happens *now* with Rust 1.27. For a basic intro to SIMD itself, you can go back to the 1.25 episode, and for the *full* stabilization plan, you can look at [RFC #2325](https://github.com/rust-lang/rfcs/blob/master/text/2325-stable-simd.md) for the master plan. Here I’m focusing on what actually landed in Rust 1.27, which is a *subset* of the full available set of features SIMD exposes. The Rust compiler, via LLVM, already does a lot of the ‘vectorization’ that SIMD gives you – the parallelization of the process across all available processing units, because everything in the *vector* in question can safely be processed in parallel. (Note that “vector” is used here in the fundamental sense, *not* in the Rust data type sense, though Rust’s `Vec` type is certainly a candidate for this kind of parallelization.) However, rustc and LLVM cannot *always* tell that something is safe to vectorize, so some functions, loops, etc. which *could* be vectorized *aren’t*. The newly stabilized `std::arch` standard library module exposes primitives which let you access the “SIMD intrinsics” for a number of platforms. An “intrinsic” is a function that is *intrinsic*, or built into, to the language or compiler. In this case, the intrinsics are actually built into the *architecture*, all the way down at the processor level; they’re *intrinsic* to the CPU. You can use the currently-stabilized set of SIMD intrinsics with the `#[cfg(...)]` attribute applied to `use` statements to get specific versions of a given function at compile time, or on the declaration of a function to choose at runtime for when a given architecture may or may not support the intrinsics in question depending on the age of the machine in question (like the x86 line). The module also exposes a number of convenience helpers, like the `is__feature_detected!` macro, which lets you generate code with fallback for when you want to use a feature if it’s available on your architecture. The upshot of all of this, for *most* Rust users, is that a bunch of the libraries you use are going to get faster. You can use these yourself where it makes sense, of course, but it’s not a most-programs-most-of-the-time concern. At the same time, there are plans to expose higher-level APIs on top of the low-level primitives now available in the `std::arch` module in the future, which should make it that much easier to use these for average developers. And those kinds of changes have the possibility to make it relatively easy for Rust to go even faster than it does today. #### `dyn Trait` The other big feature, `dyn Trait`, is a complement to the `impl Trait` feature released in 1.26. `dyn Trait` is the official replacement for the bare `Trait` syntax. Wherever you might have written something like `Box` or `&Iterator` in the past, now you’d write `Box` or `&dyn Iterator` instead. The motivation for this is two-fold: one is that, in combination with `impl Trait` it makes static vs. dynamic dispatch both *explicit* and *symmetric*. That is, you can always tell when looking at a given reference to a trait whether it’ll be *dynamically* dispatched (that is, at runtime), or *statically* dispatched (that is, “monomorphized” into distinct functions at compile time). `dyn Trait` will be *dynamically* dispatched – thus the name! – and `impl Trait` will be statically dispatched. The fact that it’s symmetric is nice – both forms have a short keyword in front of the trait – but the fact that it’s *explicit* takes us to the second reason: the bare trait version we had historically was something of a footgun for people – a place where it was easy to shoot yourself in the foot because you didn’t realize the consequences of what you might normally write. `Box` or `&Something` are ambiguous, and their performance characteristics are ambiguous as well: they could refer to a pointer to a normal type (a `struct` or `enum`), or they could refer to a *trait object*. We’ll talk more about trait objects and the related concept of object safety in the upcoming Traits Deep Dive, Part 3 episode. Here, it’s enough to note that that ambiguity – is this a normal reference or a trait object? And should I write `impl SomeTrait for SomeOtherTrait`, or should I be writing `impl SomeTrait for T where T: SomeOtherTrait`? Because those are two different things! One is implementing things for a trait object, the other for a constrained generic, but the *shorter* one that you’re more likely to write is usually *not* what you want (because you more often want the generic, not the trait object). There’s a lot more to say here, which is why there’s another episode coming up to cover it in more detail. The takeaway for today on this particular change is that anywhere you had a bare trait name in argument or return position before, you now need to change it to be `dyn Trait` instead – at least, assuming you want to keep the same dynamic-dispatch dynamics. Because you now have both `dyn Trait` and `impl Trait` at your disposal, though, it’s much easier to switch between the two as makes sense in the specific context of your program. #### Attributes updates The last couple language changes of interest that landed in 1.27 were all to do with *attributes*. The first of these is that you can now put the `#[must_use]` attribute on any function – not just any type. With this change, you can require-via-lint that the result of your function be checked even when you might not want to require that for every use of the type (or, if it’s a third-party type, might not be *able* to). The other is that you can now put attributes on generic parameters like lifetimes and types. This is a fairly obscure feature for the moment, but it’s likely to be useful for procedural macros, which are the main place you see heavy use of attributes anyway. ### Standard library stabilizations Now let’s turn our attention to standard library stabilizations. The biggest of these in 1.27 is `std:arch`, which we already talked about: it’s the module which exposes the SIMD tooling! Others were more the normal gamut of small-niceties. A few that caught my eye – you should see the [full release notes](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1270-2018-06-21) for the rest – - The new `Iterator::try_fold` and `Iterator::try_for_each` methods are both *short-circuiting* versions of their non-`try_` equivalents. So where `fold` requires that you have a non-fallible function and are responsible to manage the case where you failed on an earlier iteration yourself, `try_fold` will stop and return *immediately* if there’s a failure. The same thing goes for `try_for_each`: `for_each` keeps applying the closure no matter what, so you have to do some extra work yourself if you don’t want to operate if you’ve encountered a failure; `try_for_each` just returns immediately if you return an error. These are super handy for fairly common real-world scenarios with iterator operations! - `String::replace_range` is exactly what it sounds like: it lets you replace a specified range within a string. Note that you’re responsible for making sure you’re on a character boundary, though; it’ll panic if your range starts or ends in the middle of a character. UTF problems! - `Option::filter` is just like `Iterator::filter` (which is implemented for `Option`!), but you don’t have to call `.iter` or `.into_iter` and then `.collect` to get the result. So it’s at least potentially lower overhead *and* it’s definitely more convenient. Again, for the others, see the [release notes](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1270-2018-06-21)! ### Documentation updates There are also some nice updates to the Rust documentation. First, and something I’ve desperately wanted for a couple of years, is the ability to search *all* the Rust documentation. You’ve been able to search the API docs for a long time, but *not* the Rust books. This has been a constant source of low-level pain for everyone – and it has driven me nuts whenever I’m trying to find the right page to link in show notes! – so this change is most welcome. Second is that there’s now a guide for invoking `rustc` directly: it has its own dedicated book. Most of us use Cargo for all of our build interactions most of the time, but there are lots of times when you want to use `rustc` directly – particularly for including it in other build pipelines where the ongoing work to make Cargo integrate easily isn’t ready yet. This guide should be very helpful for those purposes! ## Rust 2018 Preview Talking about documentation makes for a nice segue into talking about our *next* topic: the Rust 2018 Edition preview! We’re getting close to the target release for the Edition! As such, there’s an early alpha release out for testing. If you want to make sure the Rust 2018 Edition release is as solid as it possibly can be, you should set up the release preview using the `rust_2018_preview` crate-level feature flag on nightly and try out the various tweaks and improvements landing in the next few months. (To do that, you just add `#[feature(rust_2018_preview)]` to the top of your `lib.rs` or `main.rs` file.) There’s an [announcement post](https://internals.rust-lang.org/t/rust-2018-an-early-preview/7776) in the internals forum and a [Rust 2018 Edition guide](#) book in the Rust docs, both of which are linked in the show notes, which give you the current status of the preview and guide you through the changes. You’ll also want to install the `rustfix` tool for some nice automatic code-modification changes: you can just `cargo install cargo-fix` and then run `cargo +nightly fix --prepare-for-2018` on your crate and it’ll correctly and losslessly update your codebase in place. This process will likely be familiar to people on the cutting edge of the JavaScript ecosystem, where codemods have become fairly common for migrating between versions of packages and even language-level changes, but it’s new for Rust, so you should definitely give it a whirl and report any errors or problems. It’s also directly relevant to the `dyn Trait` change I mentioned a couple minutes ago – it will make that fix *for* you! The current set of Rust 2018 features which *work* include the stable changes we talked about earlier in this episode and in [the Rust 1.26 news episode](https://newrustacean.com/show_notes/news/rust_1_26/): `impl Trait`, `dyn Trait`, SIMD, improved match ergonomics, and inclusive ranges and slice patterns. They also include some done-but-not-yet-stable features, which I’ll cover when they stabilize: module system improvements, simplified lifetime declarations, and the new rustfix tool I mentioned above. The non-lexical lifetimes and inference of struct lifetimes from the struct fields are still works-in-progress – more on those soon as well! ## Outro I did not have time to cover any community updates; there’s too much happening! So once again I’ll just commend [This Week in Rust](https://this-week-in-rust.org) and [the Rusty Spike podcast](https://rusty-spike.blubrry.net) for weekly updates covering a much broader swath! Also check out Matthias Endler’s [Hello Rust](https://m.youtube.com/channel/UCZ_EWaQZCZuGGfnuqUoHujw) for awesome video learning materials! Thanks so much to everyone who sponsors the show. This month’s $10-or-more sponsors included: - Daniel Collin - Nick Stevens - Peter Tillemans - Chip - Zachary Snyder - Alexander Payne - Paul Naranja - Sascha Grunert - Hans Fjällemark - Daniel Mason - Martin Heuschober - David W. Allen - Dan Abrams - Behnam Esfahbod - Aaron Turon - Matt Rudder - Derek Buckley - Vesa Khailavirta - John Rudnick - Olaf Leidinger - Anthony Deschamps - Raph Levien - Marshall Clyburn - Damien Stanton - Nathan Sculli - Ramon Buckland - Ryan Osial - Oluseyi Sonaiya - Chris Palmer You can sponsor the show at , or send a one-off at any of a number of other services listed at the website. Even more importantly, please let others know about the show – by telling them about it at a meetup, sharing it around in whatever media you use, or reviewing or recommending it in your podcast directory of choice. You can find the notes for *this* episode at . The website also has scripts and code samples for most of the teaching episodes and transcripts for many of the interviews. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/news/rust-1-28.md ================================================ # Rust 1.28 Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is a news episode for Rust 1.28. ## Sponsor: Parity Technologies Parity Technologies is sponsoring this episode because they need Rust engineers! They’re advancing the state of the art in decentralized technology, from their flagship software, the Parity Ethereum client, to building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Their next big project is Polkadot, a platform leveraging blockchain tech for scaling and interop in decentralized systems. Parity loves Rust for its trifecta of safety, speed, and correctness! If that sounds interesting, check out their jobs at paritytech.io/jobs. Thanks again to Parity! ## Rust 1.28 Rust 1.28 was a slightly smaller release than the last few have been, but that’s okay: as we’ll talk about in a few minutes, a lot of what is happening is the build-up to the 2018 Edition release. Before we get into some of the things going on with the Edition release, though, let’s dig into what *did*land with 1.28. ### Language features #### Global allocators The major feature that stabilized this release is the `#[global_allocator]` attribute and some supporting functionality in the standard library. This is a really important stabilization – not for most people’s everyday use of Rust, but for a lot of “specialized” domains. Let’s take a step back and talk about what an allocator is. An allocator is the underlying library that your programming language uses when it needs to get more memory from the system. This happens all the time in normal Rust code – every time a `Vec` needs to grow because it’s going to be full otherwise, for example – but it usually happens “under the hood” and you don’t have to think about it. Different allocators have different behaviors and characteristics. Some are better at avoiding fragmentation of the allocated heap memory, for example, or accounting for multiple threads requesting new heap memory. Rust usually uses *either* an allocator called jemalloc or the system allocator, depending on the platform. However, there are times when you simply don’t *have* a built-in system allocator, and you need to supply your own. For example, some “bare metal” environments are like this. So is my favorite Rust environment: WebAssembly. Nick Fitzgerald had a great [writeup](http://fitzgeraldnick.com/2018/02/09/wee-alloc.html) a few months ago on the [`wee_alloc`](https://github.com/rustwasm/wee_alloc) allocator he built for WebAssembly; I’ve linked both the allocator and the blog post in the show notes. Until 1.28, that required Nightly… but now it doesn’t! This is one of a number of really important steps along the path to supporting *all* those environments where you have very different needs from the normal modern operating system context. To opt into this (or, for that matter, to opt into using the system allocator on a platform where Rust normally uses jemalloc), you define a static variable, assign the relevant allocator to it (`System` in the case of the system allocator, `wee_alloc::WeeAlloc::INIT` in the case of `wee_alloc`, etc.), and then set the `#[global_allocator]` attribute on the static variable you declared. It’s actually a pretty simple way to be able to flip such an important switch! To go with all of this, there’s also a new trait in the standard library, `GlobalAllocator`, which you can implement to supply your own custom allocator. As usual, the docs are really solid here – they tell you *super* important things like the fact that custom allocator methods are not allowed to panic (this is actually undefined behavior)! As noted, of course, most of that will not matter to you *most* of the time as a Rust user. But it’s going to unlock a lot of great stuff on stable in the months ahead! #### Format string error messages Another language stabilization in Rust 1.28 is a small change in the big scheme of things, but a real quality of life improvement. The error messages you get for invalid format strings – the ones you pass to things like the `write!` and `println!` macros – are nicer now! They used to be pretty non-descriptive and at times could actually make you think the error was in the wrong place entirely. Now, they are much more in line with Rust’s nice-error-messages story in general: they tell you clearly why something is wrong and how to fix it. This remains one of my favorite things about Rust, and it’s nice to see it continuing to improve. The last language stabilization I wanted to mention – see the [release notes](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1280-2018-08-02) for *all* of them – is that unit tests marked with the `#[test]` attribute can now return `Result<(), E: Debug>`, following in the footsteps of `main` from a few releases ago. Like with the `main` change, this just eliminates a certain kind of boilerplate work we had to do when dealing with top-level `Result` instances. ### New standard library functionality Besides the `GlobalAllocator` trait we talked about a minute ago, there’s one other nice little set of standard library stabilizations – one I’ve actually *already put to use* in some WebAssembly code I’ve been working on a bit. These are the `num::NonZero*` types. These let you define an instance of a numeric type, e.g. `u8`, which *cannot* be zero – in that specific case, a `num::NonZeroU8`. The docs note that this gets you some memory layout optimizations, but *I’ll* note that there are some times this just comes up in the domain you’re trying to capture in your software, too. I’m excited in general to see more happening in the numerics side of Rust; I think the language has a lot of potential here and it’ll be nice to see it continue to grow over the next few years. And that’s pretty much it for Rust 1.28, though again there are more miscellaneous improvements in the release notes; you should always take a look to see all the details. ### A note on Rust 1.27.1. and 1.27.2 This seems like a good time to pause and note that there were two point releases for Rust 1.27. I think there was some trepidation in the ecosystem around this: did it reflect a lower degree of the commitment to stability, a higher degree of bugginess, or otherwise more problems with the process? In a word: *no*. It’s actually the opposite! I’ll link to an official Rust blog post that traces this out in more detail, but in fact these two extra point releases are a reflection of the Rust team’s growing maturity and some real *improvements* in Rust. Team-wise, there’s now a dedicated release team which manages all the hard coordination work of getting a Rust release out the door. (If you think about all the components that have to go out to get that right, you can see how that would take a whole subteam! It’s a lot of work!) That team’s existence means that shipping point releases when bugs are found is *possible* in a way it hasn’t always been. The other thing is that the specific bugs that were found were found because of the new, more robust system for borrow checking that has been developed. The borrow checker we all use today is pretty old in Rust terms, and like all software it has some bugs; the new borrow checker is much more robust and it has actually exposed these bugs. So when it comes to stable, not only will you have a much nicer time in a lot of cases (because it solves some major ergonomic problems), but it will also have many fewer such bugs over *its* lifetime. ## Rust 2018 Edition Update One other big Rust core bit of news we should cover is the revised schedule for the Rust 2018 edition release. Originally, the *next* release (1.29) was the target for the edition. Unsurprisingly, software being what it is, that date [has slipped a bit](https://internals.rust-lang.org/t/rust-2018-release-schedule-and-extended-beta/8076 "Rust 2018 Release Schedule and Extended Beta (Discourse Thread)"). The 2018 edition release is now targeted for Rust 1.31, releasing on December 6. There’s also a slightly unusual release cadence to go with it, in the interest of getting every last possible bit of polish we can. The nightly version corresponding to the Rust 1.28 release – the one out *right now*, in other words – is *Edition Preview 2*. The 1.29 release will have its *beta* channel be *Release Candidate 1* and the 1.30 release will have *its* beta be *Release Candidate 2*. That is: the Rust 2018 edition beta will be on the beta branch on the very next release: 1.29. It’ll stay there for 1.30, and then – assuming there are no catastrophic bugs or problems discovered late in the game – be promoted to stable in the 1.31 release. It’s worth elaborating on that slightly. Normally, Rust’s train model means the code that goes in a beta in one release goes into stable on the next release. We’re *intentionally* not doing that this time around. The 2018 edition will be on the beta channel in 1.29 *and* 1.30, with only bug fixes going into that. The aim here is to make sure that the 2018 edition release is as tested, polished, and solid as it possibly can be. As I noted when I first explained the Edition process earlier this year, this is a huge opportunity for presenting Rust to the world again – almost as much so as Rust 1.0 was, and probably no less important in many ways – so it’s important that we get it right! You can help with that. So please *do* help! Please go test the edition changes in your codebase – whether that’s just a small learning project, or something really substantial you’re using. If there are gaps in documentation, or weird things that show up in your testing, the Rust project *needs* to know about them. The edition guide, which I mentioned last time, continues to be the go-to source for up-to-date information about what is changing. As I noted in the last episode, you should actively try out both the new edition and the rustfix tool! We need those weird corners tested and bugs ironed out! One particular tool you should help test, if you haven’t tested it previously, is Rustfmt! Rustfmt (spelled rust-f-m-t, sometimes pronounced rustfmt) is an auto-formatting tool, which I’ve mentioned on the show in the past. It’s the kind of tool that might seem a little frustrating at first – “That’s now how I format my code!” – but can end up being a true delight in the long term. I’ve been using not only Rustfmt but also Elm-fmt when I play with Elm and Prettier in the TypeScript ecosystem every day, and I honestly can’t imagine going back to formatting my own code. I just write the actual implementation, and let the auto-formatting handle laying it out in a reasonable way. There’s [now a release candidate](https://www.ncameron.org/blog/rustfmt-1-rc/) for rustfmt out, so if you haven’t tried it, you should! If you’re using the RLS (for example in VS Code), it’s already available to you. If not, you can install it by doing `rustup install rustfmt-preview`. Once the 1.0 lands, the formatting it does will be frozen for the foreseeable future – so it behooves us to find any really odd corner cases that are left! ## Community There are also, as always, lots of interesting things happening in the Rust community, and several of these came from listeners: when I say “email me news items or things of interest,” I mean it! First, I’ve included a link in the show notes to [Nick Cameron’s LinuxConfAu 2018 tutorial](https://www.youtube.com/watch?v=vqavdUGKeb4), which is 90 minutes of goodness covering overall programming techniques in Rust. This is something I’m particularly happy to see because, as I noted in my Rust Belt Rust talk last year, video content has generally been a bit of a gap in the Rust learning story. Thanks to Ted Bedwell for sending me that link! Another great thing to check out came from Daniel Sockwell, who pointed me to a static site generator called [Gutenberg](https://getgutenberg.io/). For those of you who’ve happened to check out my started-but-very-much-on-hiatus Lightning project, I’m happy to say that you should probably just go look at Gutenberg: it does 98% of what I wanted from Lightning (and the last 2% is all to do with my own very unusual needs around academic writing). If you’ve wanted something like Jekyll or Hugo but in Rust (and, frankly, with a better templating language), Gutenberg might be what you’re looking for. Last, but *very* much not least: RustConf is this week! I’ll be there, wearing my New Rustacean t-shirt and bearing loads and loads of New Rustacean stickers, so find me and say hi! I am definitely planning on enjoying the talks (they’re going to be good, and I should know because I got to help pick them), but I’m equally looking forward to meeting many of you! ## Outro Thanks, as always, to this month’s sponsors, including: - Ramon Buckland - Matt Rudder - Marshall Clyburn - Rob Tsuk - Dan Abrams - Nathan Sculli - Derek Buckley - Sascha Grunert - Behnam Esfahbod - Peter Tillemans - David W. Allen - Paul Naranja - Anthony Deschamps - Oluseyi Sonaiya - Damien Stanton - John Rudnick - Chip - Ryan Osial - Zachary Snyder - Vesa Khailavirta - Alexander Payne - Aaron Turon - Chris Palmer - Martin Heuschober - Raph Levien - Nick Stevens - Daniel Collin - Hans Fjällemark - Daniel Mason If you’d like to sponsor the show, you can do so at [patreon.com/newrustacean](https://patreon.com/newrustacean). You can also send a one-off my way; I’ve listed a bunch of options at the show homepage, [newrustacean.com](https://newrustacean.com), which also has show notes for every episode, scripts for most episodes, and transcripts for many of the interviews. Notes for this episode are in your podcast app or at [newrustacean.com/show\_notes/news/rust\_1\_28/](https://newrustacean.com/show_notes/news/rust_1_28/). Ratings, reviews, and recommendations in podcast directories are always appreciated, but even better I love it when you tell people about the show yourself. You can reach me on Twitter @newrustacean or @chriskrycho, leave a comment in the threads on the Rust user forums, Hacker News, Lobsters, or Reddit, or you can send me an email at [hello@newrustacean.com](mailto:hello@newrustacean.com "Rust 1.28"). Until next time, happy coding! ================================================ FILE: docs/news/rust-1-31/part-1.md ================================================ # News: Rust 1.31 – The 2018 Edition, Part I Hello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust Programming Language and the people who use it. This is a news episode for Rust 1.31 and the 2018 Edition! My discussion of the 2018 edition is going to be split over two episodes, because the changes here are large and they’re a big deal! These episodes are unfortunately about a month late, but that’s because (a) I was busy helping with the final polish and push for the new Rust website, (b) I ended up dipping back into the burnout a bit from overcommitting in November and December, (c) December is *always* incredibly busy with holidays, (d) *wow* is there a lot to cover here, and (e) I was working on the interview you just heard. But here’s to more consistency (and less burnout) in 2019! ## Sponsor: [Parity Technologies](https://paritytech.io/jobs) First, thanks to the show’s current sponsor: Parity Technologies! Parity is advancing the state of the art in decentralized technology, and they’re using Rust to do it, leaning hard on its trifecta of safety, speed, and correctness. They're building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Two of the larger projects they're working on are: Substrate, a framework for building blockchains, and Polkadot, a platform leveraging blockchain tech for scaling and interoperability in decentralized systems. And they’re not just *using* Rust, they’re hiring Rust developers! So if you’d like to work on any of these projects, check out their jobs at [paritytech.io/jobs](https://paritytech.io/jobs). Now: into the show! ## The 1.31 Release This first episode on the 1.31 release will focus on two things: the mechanics of the release, and a couple of the features that appear in both editions. ### Setting the Stage Rust 1.31 was the single most important release since Rust 1.0. In many ways, it’s likely to be just as determinative of the future of the language as the 1.0 release was. The 1.0 release put Rust on a stable footing with strong backwards compatibility guarantees: it gave people a foundation to start building on, sure that the foundation would still be there in six months. (Before 1.0, that wasn’t a given! Things changed a *lot*!) But it was unquestionably a *beginning*. The ecosystem had a few important pieces already, thanks to Rust’s long history before 1.0, but many of those pieces were still quite immature—and for many kinds of projects, you were going to be building everything yourself. Over the last three and a half years, that has changed dramatically. The crates ecosystem is vibrant and growing steadily. So much so that we’ve started to have the kinds of bumps you expect with a bigger ecosystem—bad actors on crates.io or crate abandonment, for example—as well as the utility that comes from having a lot of high-quality libraries and applications now available in Rust. Unlike when 1.0 launched, in many cases it’s now quick and easy to build something in Rust. As just one small example: I now just default to using Rust if I want to quickly whip up a small command line tool, because I find it’s now just as quick and easy for me to do that as to use Node.js or Python—and with Rust’s compiler helping and far better performance than I get from JS or Python! The Rust 2018 Edition has two aims: 1. To present all the improvements that have happened gradually over the last three and a half years of a release every six weeks in a coherent way. 2. To make some small improvements in the form of *backwards compatible breaking changes*, based on what we’ve learned and built over that time. I talked about both of these ideas back when I first mentioned the Edition release – all the way back in the beginning of 2018, when we were still calling it an Epoch – but I think they’re worth digging into again and in more detail in light of the release. ### Presenting the gradual improvements Rust 1.0 was a big deal not least for telling a story to the world. The story of Rust 1.0 was: we have a stable foundation for you to build on; now, come build an awesome ecosystem with us! Since 1.0, if you’ve kept up, you’ve seen a ton of changes in the language and the ecosystem. However, that phrase, if you’ve kept up, is an important qualifier! Lots of people have *not* kept up. Plenty of people in the world undoubtedly took a look at Rust in the early 1.x days and decided *not* to dive in. Or maybe they started, but some of the gaps in the ecosystem and the rough edges in the language itself kept them from being able to progress. And while a lot of that has changed, it has changed on our 6-week, not-that-big-of-a-deal cycles. Most of these point releases don’t make a big splash, and that’s the way it should be! But it also means that most of these point releases have flown under the radar for many people who might be interested! Well, the Rust 2018 Edition release is another opportunity to tell a story to anyone out there who hasn’t been following along with all of the point releases along the way. The story now is: We have a really rich and increasingly mature ecosystem here; come build things on top of it! The standard library is far more mature now than it was in 2015, of course. So is the Crates ecosystem: many crates exist today that simply weren’t around three and a half years ago, and many crates are *stable* today that could only run on nightly three and a half years ago – especially important for core parts of the ecosystem like Serde. And the language itself is substantially easier to use, courtesy of the many improvements to the language that have landed over the last few years, from small-but-important things like better error messages, to major improvements to the module system. It’s important to communicate all those changes and improvements! An Edition is also an opportunity to get the whole ecosystem in sync. As these changes have landed piecemeal over the last three and a half years, everything from what “modern” Rust code looks like to the state of the docs has gotten a bit scattered at times – and not through anyone’s fault at all! Keeping it all perfectly aligned is probably impossible and certainly not worth it. However, in line with the idea of presenting Rust well, an Edition gives us an opportunity to make sure the docs all present the latest and best thinking, that important parts of the ecosystem are aligned on the same ways of doing things, that our tools are working together as smoothly as they can be, and so on. The net of all of this is that if you have been using Rust for the past three and a half years, and you go look at the Edition Guide, you’ll think, “Wait, that landed way before the 2018 Edition!” for a lot of the features. And that’s true! But much of the world *hasn’t* been using Rust for all of that time, and there was no single place to find all of that information previously. The Edition *Release* brings all of those changes together into one coherent announcement: here is our way-more-mature language and our way-more-mature ecosystem! And the Edition *Guide* captures all of the differences that have landed in the language over those three and a half years. ### Making some “backwards-compatible breaking changes” The other major initiative here is to make some backwards-compatible breaking changes. That phrase seems like a contradiction in terms: how can a breaking change be backwards compatible? The trick is that the only “breaking” changes allowed are at the level of surface syntax—*not* the deep semantics of the language. And there are only a couple even of these! Now, why do we even need these kinds of changes? When you design a programming language, you often reserve some identifiers – strings of characters – as keywords. These are words with special meaning that the compiler knows to do special things with. Obvious examples in Rust are things like `fn` for function declarations, `match` for match blocks, `trait` for trait definitions, and so on. You can’t write `let fn = 42;` – you’ll get the error “expected pattern, found keyword `fn`”. So when you’re building the language and make a commitment to stability, as Rust did at 1.0, you’ve locked in those keywords: because if something is *not* a keyword, then it’s fair play to use it anywhere, but if it *is* a keyword, you *can’t* use it anywhere! But of course, sometimes you change your mind on what things should be keywords further down the line. In Rust’s case, we *really* want `async` to be a keyword we can use as syntax sugar for functions which deal in `Future`s to smooth the process of writing high-performance asynchronous programs. I’ll be covering `Future`s and `async` and `await!` sometime in the first half of 2019 – it’s been on my radar for a long while, but I haven’t dug in because I’ve been waiting for a lot of it to stabilize, so that what I said wasn’t very quickly out of date and inaccurate. For now, it’s enough to know that `async` and `await` were not reserved keywords in Rust 2015, so people could (and presumably did!) use them in their codebases over the last three and a half years. They *are* reserved keywords in Rust 2018, so code that used them… would now break! Since the breaking changes are only syntactical, though, it’s relatively straightforward for the compiler to operate in different modes for the 2015 edition and the 2018 edition. I say “relatively” because I don’t want to down-play the amount of work that went into making this happen! But it’s important to realize that while there are a couple new keywords and a couple removed keywords, and one new bit of syntax for strings in support of that, that really only affects the *parse* step of the compiler: everything past that is the same in both editions. This is why the compiler can straightforwardly support 2015 and 2018 edition code side-by-side: after the parse step, *it’s the same thing*. And if things shake out as currently planned for a 2021 Edition, that will be true then as well. The compiler just has some different *parse* modes, and the underlying semantics are all still stable. This is *very* different from the breaking changes that happened in Python 3, where not only surface syntax but also important parts of the language semantics changed. ### Mechanics Let’s talk for a minute about the *mechanics* of the 2018 edition. How exactly do you opt into using the new edition, and what changes when you do? From your perspective as a user (that is, *not* as an author of the compiler itself), the only thing you have to care about is the edition flag: a value set in your `Cargo.toml` file (or passed explicitly as an argument to `rustc`) to specify the edition. It currently takes two values: `2015` or `2018` The flag was supported on stable Rust as of 1.30, and 1.31 stabilized the `2018` value for the flag. If you do *not* set the flag in your `Cargo.toml` file, the compiler will default to the 2015 edition (for backwards compatibility). From the release of 1.31 forward, any project created with `cargo new` will set the edition key to `2018` automatically. Now, if you have 2015 Edition code, *some* of it may not compile if the 2018 edition flag is set. This is why the recommended migration path is not to simply add or change that value in your `Cargo.toml`, but instead to *start* by running `cargo fix --edition`, which will safely rewrite your code to compile in both editions – or, in a few cases, tell you what kind of change you need to make yourself if it can’t see how to do it safely. (I covered `cargo fix` in a bit more detail back in [the news episode for the 1.29 and 1.30 releases](https://newrustacean.com/show_notes/news/rust_1_29_1_30/ "News: Rust 1.29 and 1.30").) *Then* you set the 2018 Edition flag in your `Cargo.toml` and you’re off to the races. `cargo fix` also has an `--edition-idioms` flag, which will further rewrite your code to be *idiomatic* in the new edition. If you want to use that flag, you should run it *after* the earlier steps. However, notice that this feature is still early in development: it’s able to do less, and what it can do doesn’t always leave your code in a compile-able state! So that’s not a *recommended* part of the edition upgrade, but ## Some of the Both-Edition Features There are a number of features which are present in the 1.31 release for *both* editions. In this episode, I’ll be covering the first handful of them: - better lifetime elision rules - library stabilizations - Cargo features ### Better lifetime elision One of the biggest win that’s on both editions is a set of improvements to lifetime elision. (The other is `const fn` types, which I’ll talk about next time!) Historically, you had to write lifetime annotations in a bunch of places that felt needless and obvious. For one, when implementing a trait on a type which has a lifetime constraint, you had to write something like `impl<'a> TheTrait for TheType<'a>`. This duplication was annoying, and it usually wasn’t adding any actual information; it was literally just noise. (**Edit: this is incorrect. See [here][correction].**) So now you can write `impl TheTrait for TheType<'a>` – no more lifetime annotation on the `impl` keyword! Even better, if you don’t need to name the lifetime to track where it belongs, you can just give it the placeholder `_` lifetime: `impl TheTrait for TheType<'_>`. That signals to everyone reading it that “hey, there’s a lifetime here, but it’s not something the trait implementation interacts with!” (**End incorrect bit.**) [correction]: https://users.rust-lang.org/t/new-rustacean-news-rust-1-31-and-the-2018-edition-part-i/24017/2?u=chriskrycho Lifetime annotations on structs also got better inference. If you were writing a struct with a lifetime `'l` and a generic `T` bound to that lifetime before, you had to write out explicitly `T: 'l` for that in the generic bounds on the struct, e.g. `struct Foo<'l, T: 'l>` – even if that relationship was obvious from how that lifetime was used in the struct. Now, if you have some property `bar: &'l T` in the struct, you can just write the top-level definition as `struct Foo<'l, T>`. A small improvement, but a welcome one. ### Library stabilizations As is usual for a point release with Rust, there are a handful of nice little library stabilizations. - The `NonZero` types (which [I talked about when they were stabilized back in Rust 1.28](https://newrustacean.com/show_notes/news/rust_1_28/ "News: Rust 1.28")) can now easily be converted into their corresponding regular (*not* non-zero) type: e.g. you can get a `u8` from a `NonZeroU8`. This is a pretty obvious stabilization: it’s always safe to go from a type which *cannot* be zero to one which *can*. - There’s another convenient new `From` implementation: to go from an `&Option` to an `Option<&T>` and from `&mut Option` to `Option<&mut T>`. It’s not uncommon to have a reference to the container type and need a reference to the type it’s containing, and these are symmetric and safe! - You can multiply time durations by unsigned 32-bit integers and 64-bit floating point numbers! ### Cargo features Cargo got one new feature in support of the module improvements I covered a bit in the last news episode (and which I’ll cover more on in the next episode): in the `Cargo.toml` file, you can now specify an external crate rename. Historically, you’d have done that with `extern crate foo as bar;`, but since it’s no longer idiomatic to have *any* `extern crate` declarations, you can specify the key `package` with the desired name in `Cargo.toml`: `foo = { version: 1.0, package = "bar" }`. This doesn’t come up all that often in my experience, but it’s handy if you have a name conflict between a third-party crate and your own crate. Cargo also got support for using HTTP/2 to download packages in parallel. While most of the time you spend doing an initial build is spent on the *build* part of it, some of it goes to downloads; parallel downloads can in principle speed this up! ## Closing We’re out of time for *this* episode; I’ll be back next week with another covering the rest of the 1.31 and 2018 Edition features. Thanks to everyone who sponsors the show! This month’s $10-or-more sponsors included: - Alexander Payne - Matt Rudder - Joseph Marhee - Rob Tsuk - Ryan Osial - James Hagans II - Bryan Stitt - Dan Abrams - Brian McCallister - Andrew Dirksen - Graham Wihlidal - Steffen Loen Sunde - Nick Gideo - Raph Levien - Daniel Mason - Behnam Esfahbod - Nick Stevens - Chris Palmer - Paul Naranja - Michael Mc Donnell - Nathan Sculli - Peter Tillemans - John Rudnick - Chip - Daniel Collin - Nicolas Pochet - Jonathan Knapp - Ramon Buckland - Jerome Froelich - beaorn - Scott Moeller - Adam Green - Embark Studios - Oluseyi Sonaiya - Martin Heuschober - Johan Andersson - Jako Danar - Anthony Deschamps If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for *this* episode at . If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/news/rust-1-31/part-2.md ================================================ # News: Rust 1.31 – The 2018 Edition, Part II Hello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust Programming Language and the people who use it. This is a news episode for Rust 1.31 and the 2018 Edition! This second part of my discussion of the 1.31 release covers the largest of the changes specific to the 2018 Edition. Note: only the largest changes! There are a handful of other small ones that you’re less likely to run into in practice but which are nice improvements—you should certainly read [the Edition Guide](https://doc.rust-lang.org/stable/edition-guide/) in full! ## Sponsor: [Parity Technologies](https://paritytech.io/jobs) First though, the show’s current sponsor: Parity Technologies! Parity is advancing the state of the art in decentralized technology, and they’re using Rust to do it, leaning hard on its trifecta of safety, speed, and correctness. They're building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Two of the larger projects they're working on are: Substrate, a framework for building blockchains, and Polkadot, a platform leveraging blockchain tech for scaling and interoperability in decentralized systems. And they’re not just *using* Rust, they’re hiring Rust developers! So if you’d like to work on any of these projects, check out their jobs at [paritytech.io/jobs](https://paritytech.io/jobs). ## More 1.31 Both-Edition Features! Okay, now let’s dig into the remaining changes in the 1.31 release which are in both editions, as well as all the features specific to the 2018 edition! ### Tooling stabilizations Up first, there are a bunch of tooling-related stabilizations: Clippy, rustfmt, and support for lint attributes in your code. Up first is Clippy: named for the old paperclip “helper” in Microsoft Office, which would prompt you with little snippets like “It looks like you’re trying to write a letter…,” Clippy provides a bunch of extra lints to make for more maintainable, more idiomatic Rust code. It’s now shipped standard, and it should help you make sure that what you’re writing isn’t just strictly safe in the Rust-makes-sure-it’s-memory-safe category, but also *good* Rust and much more likely to do what you want. Clippy has been around for a long time; but it’s now part of the default tooling that ships with the language. You should turn on the Clippy integration in your editor—you can use it in anything from Vim to Visual Studio Code – and get writing better Rust! Next up is rustfmt, the automatic code formatting tool. rustfmt has been in development for close on three years now: the repository reports the first commit was in April 2016! Since then, it has gone through a lengthy process of developing both the tool and the official formatting standards—the formatting standards actually got their own RFC process! The result is a really fast, really nice tool that in my experience works really well and produces *great* results 99% of the time and *results I can live with* the last 1% of the time: even when they’re not what I would choose, they’re *fine*—and having an auto-formatter on your code is genuinely great. I’ve used Prettier for auto-formatted JavaScript and TypeScript for the last few years, and even with its quirks, I can’t imagine ever going back to *not* having an auto-formatter. One of my favorite things about it is that I just write stuff out, not worrying about formatting at *all*, because I know when I save the file it’ll get formatted into something nice. As of Rust 1.31 and the 2018 edition, rustfmt is stable and at 1.0! This means that the tool guarantees backwards compatibility: if you run it on your code, it will consistently give the same results going forward. (During the development period pre-1.0 this was not true.) You can now integrate it into your commit or continuous integration flow and be confident it won’t give you spurious results or a lot of churn and noise! Finally, there are some nice new language features in the form of tool-level attributes for lints. For both Clippy and rustfmt, there may be specific places where you want to explicitly opt out of the tool’s behavior—you may have specific reasons to format things in a specific way (for example in macros), or you have a specific reason to ignore Clippy’s advice in some spot. Historically, you had to write tool rules with the `#[cfg_attr(...)]` attribute, which was *long*: you had to write `#[cfg_attr(feature = "cargo-clippy", allow(iter_nth)]` to disable the `iter_nth` lint. Now you can just write `#[allow(clippy::iter_nth)]`: so much better! ### `const fn` The last big feature to stabilize on both the 2015 and 2018 editions is `const fn`. A `const fn` is a function which can has a *constant*-valued expression as its result, and which can therefore be computed at compile time instead of at runtime. (There’s a specific subset of Rust which is currently allowed in `const fn`s to guarantee that you will indeed always get a constant value for the result of the function; I’ll refer you to the [reference](https://doc.rust-lang.org/reference/items/functions.html#const-functions) for details.) The compiler is *allowed* to compute the result of a `const fn` in any context, but is only *required* to do so in [“const contexts”](https://doc.rust-lang.org/reference/const_eval.html#const-context)—that is, contexts where the expression in question must be evaluated at compiler time. The const contexts in the language today are: - array length expressions, like the `3` after `i32` in `let array: [i32; 3] = [1, 2, 3];` - repeat length expressions, like the `5` in `[0; 5]`, which produces an array of five elements, all set to the value `0` - and initializers for constants, statics, and enum discriminants. That’s a fairly short list at present, so the number of places where the compiler is guaranteed to run a `const fn`—but remember: the compiler is *allowed* to evaluate `const fn`s in lots of places. That list is likely to expand in the future, as is the list of allowed kinds of operations in a `const fn`, but we now have a starting point for this kind of optimization. And “optimization" is the right description: `const fn` can be pretty big deal for runtime performance! If you have an operation which takes a while to run, but can be reused throughout the life of the program, you can save your users a *lot* of overhead with `const fn` by doing that compilation once on the source machine instead of repeatedly on every user’s machine, and even repeatedly in the runtime of the program. It’s like function inlining but with superpowers. However, as is nearly always the case for the triangle of runtime performance, safety, and compile time performance, we’re paying for it somewhere: in this case, since the computation happens at compile time, you’re paying for it… at compile time. That’s sometimes exactly the right tradeoff, but as with all tradeoffs, it’s very important you understand that you’r making it so you can make it explicitly! In many cases, the benefit of doing a `const fn` is so small that it’s *not* worth it! However, especially in some of high-performance numeric computing contexts, this is a game-changer, and it has long been one of the reasons to continue preferring C++ over Rust. ## 2018 Edition Features Finally, let’s talk about the Edition-only features: - changes to the language syntax, - improvements to the module system, - and non-lexical lifetimes! ### Syntax changes The syntax changes are *very* small. It’s no exaggeration to say that this is one of the smallest sets of “breaking” changes a language has seen. The only *removals* are removing a few new keywords from the set of previously-valid identifiers for item bindings: meaning, since they’re keywords now, you can’t use them to name a function or a variable or what-have-you anymore. Also, there are only a few additions: the new keywords `dyn`, `async`, `await`, and `try`. But wait, you say! Wasn’t `dyn` already a keyword in the 2015 edition? Didn’t you talk about it back in [the Rust 1.27 episode](https://newrustacean.com/show_notes/news/rust_1_27/index.html), when `dyn Trait` was stabilized? The answer is: *kind of*. I did indeed talk about it then, but `dyn` was *not* a full keyword in the 2015 edition: it was what the Rust reference calls a “weak” keyword—what you’ll sometimes hear referred to as a *contextual* keyword: that is, a keyword that’s not a keyword everywhere, but only in specific locations in the language’s grammar. Contextual keywords are essentially workarounds for times when you *reaaaally* wish you’d made a keyword before, but you didn’t, but you can *kind of* make it work by saying “it’s a keyword in these specific locations.” The downside to them is that they’re more work for the lexing phase of the compiler, where it turns all the various tokens into their language-level semantics. Is `dyn` a keyword, or just a regular identifier? Well, in the 2015 edition, we don’t know until we see the *next* item! The 2018 Edition promotes it to being a full keyword, so it’s now invalid to use as any other kind of identifier (whereas it was still legal to use in most positions in the 2015 edition). `async`, `await`, and `try` are now all *reserved* keywords: none of them mean anything on stable Rust today, but the language design team expects they may in the future. `async` and `await` are *definitely* doing to be used as part of the story around asynchronous programming with the `Future` type, and we expect that to stabilize sometime here in the first half of 2019. `try` is a bit murkier: there have been a lot of discussions about ways we might improve error-handling ergonomics, and it’s not yet clear that any of them are winners—`try` is reserved for the 2018 edition to make a number of them *possible*, but it’s an open question whether any changes will happen there. Now, what if you have a codebase where you heavily used one of these keywords—say, if you were using `async` in a bunch of places as a shorthand for something? Rust has your back here: you don’t have to do a global find-and-replace operation. The `cargo fix --edition` invocation we covered in previous news episodes will rewrite any uses of these new keywords using another new feature in the language: raw identifiers. You can now write an identifier prefixed by `r#`. (This doesn’t come out of nowhere: the format is similar to [the raw string syntax](https://doc.rust-lang.org/stable/reference/tokens.html#string-literals)—which you may never have run into; I’ve linked it in the show notes to look at if you haven’t.) Thus, `cargo fix --edition` will rewrite every use of `async` as an *identifier* as `r#async`. It’s not the prettiest thing in the world, but it solves the problem nicely—and it means you can now use *any* keyword as an identifier, as long as you give it that leading `r#`. ### Module system improvements Up next: the module system improvements. We covered the first major part of this when it was stabilized with Rust 1.30—so it’s obviously compatible with Rust 2015! The remaining piece ([“uniform paths”](https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html#uniform-paths)) will be part of the 2018 edition, but remains nightly-only. As such, I’ll refer you to [the news episode for 1.30](https://newrustacean.com/show_notes/news/rust_1_29_1_30/index.html) for a full walkthrough on the changes which have already stabilized, and to the *future* for the uniform paths component—but I didn’t want to push out two episodes on the Edition release without at least *mentioning* it! It’s a really big improvement and an important change, so please check out the earlier episode and read [the Edition guide section on the changes](https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html)! ### Non-lexical lifetimes There is *one* major feature that is landing as part of the 2018 Edition that wasn’t part of previous releases: *non-lexical lifetimes*. This is something the Rust compiler and language team have been working toward for *years*: a massive improvement to the way that lifetime tracking works in the compiler. (As an aside that I think is kind of fun: a lot of this work was unlocked by something I talked about in depth in [the very first dedicated news episode, years ago, when I covered MIR](https://newrustacean.com/show_notes/news/_1/): the mid-level intermediate representation in the compiler.) It’s worth note, before I dig into the details, that this is *presently* landing in the 2018 Edition only, but the team expects to back-port it to work with 2015 Edition Rust as well. The name of this feature, non-lexical lifetimes, gives us the pieces we need to understand what’s changing. At some point, we’ll all just thinking of these as “lifetimes” plain and simple, but for right now, they’re named in contrast with how lifetimes have worked historically. To this point, lifetimes were “lexical”: that is, they were the same as lexical scopes—that is, *blocks*. If you borrowed something anywhere in a block—a function, a for loop, a match block, etc.—it was borrowed until the end of the curly braces for that block. This is why one of the workarounds for a fair number of situations you’d run into with the borrow-checker has been to introduce a local block: then the lifetime and borrow analysis the compiler did could understand that something was no longer borrowed at the end of that block, and the rest of your function could do what you wanted. This is super frustrating, though: you as a user can look at it and say, “No, Rust, I’m *done* with this borrow up here! Why can’t you see that I’m no longer borrowing it and let me borrow it again later! Agh!” And the block workaround is ugly and even that doesn’t always get you where you want. So, for the last several years—this has been an in-progress effort for most of the life of the 2015 Edition!—the team has been working on a new approach to the borrow checker’s understanding of lifetimes. This is tricky because the new version has to get three things right: 1. It has to let through everything that the old borrow checker let through. 2. It has to properly let through as many new things as it can. 3. It has to be sound—that is, it has to rightly uphold all of Rust’s normal memory guarantees. And point (3) actually trumps points (1) and (2): correctness is the most important thing for the borrow checker. And this isn’t just hypothetical! The new engine identified potential soundness bugs that got through with the old borrow checker—the bugs which triggered the 1.27.1 and 1.27.2 releases earlier this year. Non-lexical lifetimes work by tracking a much more sophisticated graph of where and how *values* and the *references to them* interact. For the extremely nitty-gritty details, I’ll direct you to a series of blog posts by Niko Matsakis (dating back to April 2016!), which show the evolution of this in detail. At a high level, it’s enough to understand that non-lexical lifetimes use the control-flow graph from the mid-level intermediate representation in the compiler. That control-flow graph makes it possible for the compiler to determine when a given value is live (and thus valid to have a reference to) and when a given reference is live (and thus valid or invalid for there to be *other* references to that data). This is one of the advantages of something like MIR: while you’d never want to *write* something in the extremely long-form style that MIR uses, it makes all these kinds of relationships extremely clear in a way that the rest of the compiler can take advantage of. There are also a couple of other kinds of “smarter” lifetimes that landed as part of this feature. One of my favorite examples of this that makes it easy to see the improvement is [a simple example](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f497716877668a5f0dc904e24ffc207a) I’ve linked from the show notes, where you call `vec.push(vec.len())`. On Rust 2015, this just doesn’t work: `vec.push()` mutably borrows `vec` and then `vec.len` tries to borrow it as well, and the compiler just says *Nope!* In Rust 2018, it works fine, because the compiler can tell that the `vec.len()` effectively happens *before* `vec.push()` does: the temporary value created from `vec.len()` by the compiler is the same as the workaround you’d do yourself by actually writing out an intermediate value before calling `vec.push()`. There are tons of these kinds of wins, and the net of it is that a lot of things where you historically would have “fought with the borrow checker” you won’t have to anymore! ## Closing And that’s it! This is a huge release, and I think it sets Rust up really well for the future. Since the 1.0 release, we’ve seen a ton of clean-up and improvement, and this is a great time to introduce Rust to colleagues or friends who haven’t heard about it or who looked at it in the past and decided to wait before diving in. Thanks to everyone who sponsors the show! This month’s $10-or-more sponsors included: - Daniel Collin - Scott Moeller - Ramon Buckland - Michael Mc Donnell - Johan Andersson - Oluseyi Sonaiya - Steffen Loen Sunde - Anthony Deschamps - Rob Tsuk - Behnam Esfahbod - Matt Rudder - Ryan Osial - Embark Studios - Nick Stevens - Paul Naranja - John Rudnick - Daniel Mason - Nicolas Pochet - Andrew Dirksen - Alexander Payne - Graham Wihlidal - Jerome Froelich - beaorn - Dan Abrams - Joseph Marhee - Chip - Nathan Sculli - Adam Green - Chris Palmer - James Hagans II - Jonathan Knapp - Raph Levien - Peter Tillemans - Nick Gideo - Bryan Stitt - Jako Danar - Brian McCallister - Martin Heuschober If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for *this* episode at . If you like the show, please help others find it—by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/news/rust-1-32.md ================================================ # News: Rust 1.32 Hello! I’m Chris Krycho and this is New Rustacean: a show about the Rust Programming Language and the people who use it. This is a news episode for Rust 1.32. ## Sponsor: Parity First up, Parity is back sponsoring the show, because they want to hire Rust developers. A.k.a. *you*! Parity is advancing the state of the art in decentralized technology, and they’re using Rust to do it, leaning hard on its trifecta of performance, reliability, and productivity. They're building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Two of the larger projects they're working on are: Substrate, a framework for building blockchains, and Polkadot, a platform leveraging blockchain tech for scaling and interoperability in decentralized systems. If that sounds interesting, check out their jobs at ! ## Rust 1.32 Okay, so let’s dig into what will be the *last* news episode for a while! Because I got the Rust 1.31 episodes out late, this is a quirky month with three news episodes in it! Gladly, there won’t be another one for about six weeks and you should get *at least* one bonus episode and one teaching episode between then and now! Okay, so let's jump in, because Rust did *not* slow down with this release. ### `dbg!` First up is the `dbg!` macros. If you're like me, you *sometimes* use a debugger like lldb, but just as often you're using the `println!` or `eprintln!` macros to dump the output and state of some part of your program while you're working out why some data structure isn't in *quite* the shape you wanted. This is *fine*, but it's definitely not *amazing*, and it's incredibly repetitive, and you always have to remember the slightly odd debug format string invocation: `{:?}` or, to pretty-print the debug output, `{:#?}`. (Confession: I always forget the latter even exists, but it makes the output way more useful!) Rust 1.32 to the rescue with `dbg!`. You still have to `#[derive(Debug)]` for types which you want to be able to print this way (though in truth I do this for nearly every type in my programs anyway). But once you do, you can just do `dbg!(some_value);`: no format string required. This is a quality-of-life win, not some kind of huge change to the language, but I *love* it. ### Breaking up with jemalloc Up next is a *really important* but also somewhat *in the weeds* kind of change. As of Rust 1.32, all platforms now use the system allocator by default, instead of jemalloc. I talked a bit about this in the episode for Rust 1.28, when Rust got the *ability* to switch allocators—that was important foundational work for this change, so that people who *want* to keep jemalloc can. Also, this is not actually a change for *all* platforms; Windows already used the system allocator. As a quick refresher: the *allocator* is the piece of your program environment which gives you memory when you need it. A memory allocator has a couple responsibilities: - it has to give you *enough* memory for the amount you need, e.g. if you need to double the size of a `Vec` - it has to reliably handle conditions when your system is out of memory (which can happen if, say, you have too many instances of Slack up… sorry, too soon) - it has to try to keep the allocations it makes well-structured, so that it can *keep* providing memory as needed – if things get chunked up weirdly, there may be enough *total* memory available for a given request, but none of it in big enough individual *blocks* And there are, no doubt, more that I'm unaware of; I've never actually needed to deal with allocators in detail. But like a lot of things: when you *are* dealing with them, it's super important! jemalloc does all of those things, but it has its own set of quirks and behaviors, and the reason Rust was using it had to do with the time in Rust's history where it had a green-threading model—more like Erlang or Go! That time passed *ages* ago and it makes the most sense to *default* to the system allocator and let people opt in other directions if they have good reason to. So: now that's what we do! And one big and immediate upside of this is that your binaries should be smaller. I saw [one user on Twitter][smaller] report that they saw "hello world" drop 576kb to 280kb: almost 50% smaller. Obviously you're not going to see 50% reduction in the size of your app by doing this in general—it's probably more like a constant size decrease, and on the order of hundreds of kilobytes, and the specific amount will depend on the specifics of your system. It won't change at all on Windows, for example, since jemalloc was *never* the default on Windows! A nice little win in any case. [smaller]: https://twitter.com/softprops/status/1086723200095059972 ### Unified paths Probably the biggest language feature landing in this release is uniform paths: the final part of the module system improvements I've talked about over the last few months. "Uniform paths" here means that the path system now works exactly the same way for imports—that is, `use` statements—as it does for other references to paths. Historically, a `use` path always started from the root of the crate, while other paths always started from their current location in the crate. This meant that in your root module, they *appeared* to work the same way, because *by coincidence*, they did—but as soon as you had a submodule, the two kinds of paths stopped working the same way. The confusion that sprung from this difference was one of the major motivators for reforming how module paths work in Rust. Paths got a lot clearer already, and I talked about that a few episodes back when the "path clarity" changes landed. Uniform paths are the final touch, though, and they make for a much cleaner and much easier-to-learn system: you can always use the *same* kind of path from anywhere in your crate, in any kind of path statement, and it works the same way. So if you write `some_module::some_item` in a use statement, that's a relative path, just like it would be if you were writing a path to an item for resolving it in a `where` clause or a type definition or something. ### `Self`-absorption There is one other language level feature out in this release: a bunch more places where you can use the `Self` type. One is that you can use `Self` as the name of the type when constructing unit or tuple structs, like when you are using a tuple struct for the newtype pattern to give yourself a type-safe wrapper for another type (e.g. `struct Email(String)`, to give yourself a tool for differentiating between strings which have been validated as emails and strings which are just, well, strings): in an `impl` block for `Email`, you could write `Self(some_validated_string)` instead of `Email(some_validated_string)` for constructing the type. Similarly, you can use the `Self` shorthand in type definitions. The release notes give the example of a constrained `List` type, where you want it to be an *ordered* list: you might write it with a `where` clause whose body was `Self: PartialOrd` instead of `List: PartialOrder>` and so on. It's a nice short-hand. Nothing world-changing, but in each of these cases it means you can write the type *just once* and refer to it as `Self` after that, as you already can in many other places. ### Library stabilizations! This release also saw a number of neat library stabilizations beyond the fancy new `dbg!` macro. First up, the first major batch of standard library use of `const fn` landed! This should lead to a small but meaningful increase in the performance of these at runtime! A handful of illustrative examples: `char::is_ascii`, `str::as_ptr`, `Ipv6Addr::new`, and `Duration::as_secs`. Any time you're in a const context, these will now be evaluated at compile time, so they never have to be calculated by the running program. Second, there are a bunch of new handlers to convert little and big endian bytes to numbers in Rust's native (i.e. the local) representation. If you've never encountered the idea of endianness before, it's the order in which information is stored in the binary value that makes up a byte: if you're reading them as a set of numbers, is the first bit on the left side of a byte, or the right side of a byte? And the same for bytes: is the smallest/least-significant byte first or last for a whole data structure? Here, "least significant" means *smallest*, e.g. in binary the bit representing 1 is smaller, or less significant than the bit representing 2, which is smaller—less significant—than the bit representing 4, and so on. Little-endian puts the least significant bits and bytes first; big-endian puts the least significant bits and bytes *last*. This doesn't often come up in most high-level programming, but when you're dealing with network protocols or low-level hardware concerns, it can be *very* important. So now Rust has convenient handlers to take data from either representation and convert them into numbers, where you no longer have to concern yourself with endianness. (**Edit:** these existed for quite some time; the change is that they, like the other bits mentioned above, are now `const fn`.) ## Community Finally, a few things that recently came to my attention in the last few weeks—which may not be *new*, but which were at least new to *me*! ### [Amethyst] The first of those is [Amethyst]: a game engine [written in Rust]. As an aside, this one came in via listener Alexander Lozada, who did what I'm always asking people to do and emailed me about it! Amethyst is aiming to be both incredibly fast—it leans hard on Rust's ability to do safe multi-threaded computation—and also idiomatic and easy to use for game developers. It uses the Entity-Component-System architecture that is, as I understand, a standard pattern in game development (the [keynote at RustConf 2018][keynote] dug into why that's the case *and* into how Rust is a really great fit for it). Amethyst has [a whole book] devoted to using it, a bunch of [examples] to help you see how to get started with it, lots of [docs], integration *today* with OpenGL and work in progress for Vulkan and Metal… basically, this is an attempt to make game-development in Rust *easy and good*, and I think that's fantastic. [Amethyst]: https://www.amethyst.rs/ [written in Rust]: https://github.com/amethyst/amethyst [keynote]: https://m.youtube.com/watch?v=aKLntZcp27M [a whole book]: https://www.amethyst.rs/book/latest/ [examples]: https://github.com/amethyst/amethyst/tree/v0.10.0/examples [docs]: https://www.amethyst.rs/book/latest/ ### [`insta`][insta] Another neat crate I saw fly across my radar is [`insta`][insta]—a brand new tool for *snapshot testing* in Rust. Snapshot testing is a style of testing that has gained a ton of steam in front-end web development in the last few years, especially in the React community. The basic idea is: you generate an expected value—often for something a bit more complicated than just some small piece of data; in the front end web world it's often something like some rendered DOM—and store it in a separate file from the test. When you run the tests after that, they simply diff their output against the contents of that file. If you make an intentional change that alters the output you expect, you update the snapshot. This can make your test code a *lot* easier to read and maintain: instead of having to basically include all of that output directly in the body of your test, you can store it *beside* the tests and let your test code simply do the work of describing what you expect to happen. [insta]: https://crates.io/crates/insta The `insta` crate applies this exact same model to items in Rust: it works with anything which supports either the [`Debug`][debug] trait or [Serde]'s [`Deserialize`][de] trait. In your tests, you use one of the macros it supplies: [debug]: https://doc.rust-lang.org/std/fmt/trait.Debug.html [Serde]: https://docs.serde.rs/serde/ [de]: https://docs.serde.rs/serde/trait.Deserialize.html - `assert_snapshot_matches!` compares basic strings. - `assert_debug_snapshot_matches!` compares the output of debug printing a data structure. - if you turn on the `serialize` feature in your crate, you can use `assert_serialized_snapshot_matches!` to compare any type which supports the Serde `Deserialize` trait: it'll generate YAML for the snapshot and compare that output. When you run your tests the first time, you make sure they fail the way you *expect* them to if there is no snapshot, and then generate the snapshot by setting the `INSTA_UPDATE` environment variable to `1` with your `cargo test` invocation: that will *generate* the snapshots for future use. As soon as I looked at this I realized I *want* it very much, for an easier way to test a lot of the various pieces of my (still moving, just very slowly) static site generator project: I have a number of tests in a working branch which just make sure that the tool serializes and deserializes various complex data structures in exactly the way I want, and snapshots would help a *ton* with them. ## Closing As a bit of personal news here at the end of the episode: I’m starting a new job on the 28th (a week from when this episode releases)—I'm going to be working on front-end infrastructure at LinkedIn. I'm excited about this role for a *lot* of reasons, but one near the top of the list is that there's a very good chance I will actually get to write some Rust in that role over the next year! Thinking on that as I wrote up this script also made me reflect a bit on the longevity of this show! It’s kind of amazing to me that New Rustacean has run as long as it has and has had the success it has: I have been making this show longer than I’ll have had *any job*. That’s thanks to all of you who listen, and especially to the folks who’ve seen fit to sponsor the show. Thank you! And more to come! On that note, this month’s $10-or-more-sponsors included: - Bryan Stitt - Oluseyi Sonaiya - Daniel Collin - Scott Moeller - Behnam Esfahbod - Rob Tsuk - Paul Naranja - Johan Andersson - Raph Levien - Chip - Andrew Dirksen - Matt Rudder - Joseph Marhee - Nicolas Pochet - Nick Gideo - beaorn - Jonathan Knapp - Alexander Payne - Dan Abrams - Nathan Sculli - Chris Palmer - Jerome Froelich - Brian McCallister - Ramon Buckland - Michael Mc Donnell - Peter Tillemans - Daniel Mason - Anthony Deschamps - James Hagans II - John Rudnick - Nick Stevens - Jako Danar - Embark Studios - Graham Wihlidal - Ryan Osial - Martin Heuschober - Evan Stoll You can sponsor the show at patreon.com/newrustacean or via other services listed on the show website, . There, you’ll also find show notes, including links to things I talk about, scripts, code samples, and interview transcripts. The notes for *this* episode are at . Please recommend the show to others if you like it, whether in person, via your podcast directory, or otherwise! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/news/rust-1.33-and-1.34.md ================================================ # News: Rust 1.33 and 1.34 Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is a news episode for Rust 1.33 and 1.34. As I mentioned in a recent bonus episode, March was *extremely* full with my prep for a workshop at EmberConf—this episode covers both 1.33 and 1.34 as a result. ## Sponsor: Parity Before we dive in, Parity is back sponsoring the show—because they want to hire *you* to come work in Rust with them! Parity is advancing the state of the art in decentralized technology, and they’re using Rust to do it, leaning hard on its trifecta of performance, reliability, and productivity. They're building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Two of the larger projects they're working on are: Substrate, a framework for building blockchains, and Polkadot, a platform leveraging blockchain tech for scaling and interoperability in decentralized systems. If that sounds interesting, check out their jobs at ! ## Rust 1.33 Release Okay, so let’s talk Rust 1.33. ### Moar `const fn` fun! 1.33 landed yet more features around `const fn`, allowing you to do yet more compile-time evaluation. As you may recall from my discussion of these in the Rust 2018 Edition episodes, there’s a tradeoff between these: you spend more time compiling, but with the benefit of effectively no runtime cost at *all* for getting the results of these computations. Deployed effectively, these can lead to significant improvements in the speed of your program or library. The 1.33 features are: - Assignment! Yes, you literally couldn’t use assignment in `const fn`s before. - That includes things like the `+=` and `-=` operators. - It also works down into structs or when indexing into arrays, so you can do things `point.x += some_offset`.. - `let` bindings: as long as *they* in turn evaluate to constant results, they’re good. - The same goes for `let mut`. - You can use destructuring patterns if they *always* work. So if you have a struct `Point` with fields `x`, `y`, and `z`, you can write `let Point { x, y, z } = some_point;`, or you can do the same with tuples, and so on. - You can use `const unsafe fn` from `const fn` now. (I was actually kind of surprised this wasn’t the case already!) The net of that is that a *lot* of stuff can now be `const fn` which couldn’t before, and the Rust standard library now takes advantage of that. #### Standard library changes for `const fn` - The `overflowing_` and `wrapping_` math operations are now `const fn` for all numeric types. - So are `is_positive` and `is_negative`. - A *bunch* of handlers around binaries numbers and endianness—things like `leading_zeros` and `to_le` and `from_le`, for example. I’m really curious to see if anyone has benchmarked representative programs and seen if or how this has improved run times. ### `Pin` One of the most important items in 1.33 was the stabilization of the `Pin` type. `Pin` is a type representing an object which is *guaranteed* to keep the same location in memory throughout its life. Normally, objects in Rust do *not* have this property: they can *move*. This applies to when we talking “moving” in the context ownership, and in that context the specific dynamics of how objects move around in memory vary—they’re compiler-defined, in general, and that lets the compiler make a lot of interesting optimizations. It also applies to pointers: you can move the objects that a mutable reference or a `Box` point to. There are, in short, a *lot* of ways that things can move in Rust. But there are times when you need to be able to guarantee that an object does *not* move, and for that we have `Pin`. When specifically might you want that? The API docs (and the announcement blog post) give the example of a self-referential struct type. If a type has a pointer to itself, and it moves, the pointer would become invalid—and this is undefined behavior. We don’t want that! Now, it wasn’t immediately apparent to me when you’d want that, so I poked around a bit, and withoutboats’ [RFC for this API][RFC #2349] proved *extremely* helpful, so I strongly recommend you read it. One prime case where you need this is in a *generator*, which (to hand-wave a *lot*) a function which can suspend operation at one point in time and resume again later. (In JavaScript and Python, you may have seen this expressed with the `yield` keyword.) Making this work requires that you basically take the current stack frame and save it—turn it into an object that you can manipulate: storing it for reference, adding and removing things from it over time, etc.: at the end of the day, it’s a kind of state machine, and keeping track of and updating its internal state means keeping references to itself. This was `unsafe` in the formal Rust sense before the `Pin` type landed; `Pin` lets us express the guarantees we need to make this kind of thing safe. It’s similarly necessary to make the futures and async work viable. [RFC #2349]: https://github.com/rust-lang/rfcs/blob/master/text/2349-pin.md The stabilization adds the following new APIs: - `Pin

` is a new type where the type parameter `P` is *any pointer type*—`&mut MyStruct`, `Box`, `Rc`, etc. This wraps those pointers in mechanics which forbid the use of *move* operations on the *value* behind the pointer. The *behavior* of something like `Pin>` is pretty much just like `Box`… except that you cannot do things which cause moves, and that includes getting the actual `Box` itself. The same goes for `Pin<&mut T>`—you can do basically all the normal things you can do with a referenced mutable value in Rust, *except move it*. No `mem::swap` calls here to exchange what is sitting in that memory for something else! - `Unpin` is a matching trait, which effectively *undoes* the effect of `Pin`. That might sound strange, but it turns out that most types *don’t* have any need for this kind of memory-location stability. For example, an `i32` just doesn’t care whether it’s in the same spot: it’ll never be self-referencing anything… because it’s just an integer! As a result, `Unpin` is *automatically* implemented for most types. You may remember that this is true for a number of other traits in the standard library, most notably `Send` and `Sync`. Like `Send` and `Sync`, `Unpin` is a trait you can implement yourself, but also one you can explicitly opt *out* of for a given type by writing `impl !Unpin` for that type. Opting out means `Pin` has its defined effect: it cannot be moved. In addition to these two types, there are some important rules about what it means to implement the `Drop` trait for a pinned type, and also about the relationship between a pinned struct and its fields. Rather than trying to explain those in this news episode, I will simply refer you to the really excellent and quite details [API docs][std::pin], which walk through these in detail and also provide some great examples of actual implementations with `Pin` and `Unpin`! [std::pin]: https://doc.rust-lang.org/std/pin/index.html ### An Import Nicety One last note for Rust 1.33: there’s a small feature I *really* appreciate in the module import syntax. You can now import an item as `_`: the same way you can use `_` to say “I don’t care about this *value name*” in a function or match expression, you can now use it to say “I don’t care about this *module name*” in a `use` statement. This is particularly handy for when you want to import a module’s trait implementations without importing (or aliasing) its name. I ran into exactly this myself not that long ago, so I was super happy to see this! ## Rust 1.34 Now, let’s dig into Rust 1.34. There are two big features I want to talk about here: alternative cargo registries, and the `TryFrom` trait stabilizing. Before I dig into those, a few library stabilizations I think are interesting (as always, you should take a look at the [full release notes][1.34 release notes] for the full list). [1.34 release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1340-2019-04-11 One API that stabilized is the `std::any::type_id` function. This lets you take a type and determine whether its compiler-generated, globally unique identifier is the same as that for a specific type. You can’t see into `TypeId`s, but you can use this for a certain amount of runtime reflection on otherwise opaque types. So, for example, you can define a function which determines if two types are the same: ```rust use std::any::{Any, TypeId}; fn same_type(a: &A, b: &B) -> bool { a.type_id() == b.type_id() } ``` You can do a lot more with this when you combine it with the existing `TypeId` type and its implementations, which have been stable since Rust 1.0. This new `type_id()` helper just allows for some nice improvements to those runtime metaprogramming features! As an aside: we haven’t talked about `Any` before, but it is roughly what it sounds like: a trait type which allows you to introduce a degree of runtime dynamicism into your types, by saying “This thing can be *anything*” – you can then do the kinds of dynamic programming you might be used to in other, more, uhh, *dynamically* typed languages. It’s not necessarily something you reach for often in Rust, but it’s nice that it’s here and nice that it continues to get some love! ### `TryFrom` Up next, one of those two big items I mentioned: the `TryFrom` trait stabilized (and with it, the matching `TryInto`). This is a really, really nice win, and you probably know it if you’ve been programming Rust for any length of time. The existing `From` trait is great, but it *requires* that your `from` function *always succeeds*, and there are just an awful lot of times when you *cannot* write a function converting from one type to another in a way that always succeeds. Idiomatic Rust has usually worked around this by providing a `try_from` function which takes in the source type and returns a `Result` of the target type and the causes for failure… but because this has been done in an ad hoc way from codebase to codebase, you could easily end up in a spot where different implementations supplied their *own* `TryFrom` trait, or no such trait at all, and things were a bit of a patchwork as result. Stabilizing `TryFrom` solves this nicely: we now have a standard library trait that everyone can implement and use with their own types. `TryFrom` requires you to supply an associated type named `Error`, which is the error output, and a function `try_from` which returns a `Result` of target type or that associated `Error` type. `TryInto` is the inverse of `TryFrom`, just as `Into` is the inverse of `From`, so if you have an `impl TryFrom for U` you automatically also get `TryInto for T`. Finally, as a convenience for dealing with APIs which expect `Result`s, `TryFrom` is automatically implemented for `From` implementors, but which can never fail (you’ll never get the error case of the `Result`). This is one of those nice “fix a papercut and do it well” kinds of changes I love to see. ### Alternative registries Okay, last but perhaps most importantly for many large organizations: support for alternative registries for Cargo is now stable! In general, many individuals and companies are happy to use the normal crates.io registry for finding and using packages. However, in a number of contexts—organizations with specific security needs, often including *large* organizations—crates.io (excellent though it is) doesn’t meet the specific requirements of the organization for vetting the packages it uses. Additionally, many organizations of *all* sizes need *private* registries of packages which are internal-only: it’s easy to forget if you’re doing a lot of open-source stuff, but everything on crates.io is public! Organizations with either of those sets of needs will often set up their own private registries for packages they host—alternative npm registries, Nuget repositories, etc. As an example of this: my own employer, LinkedIn, has very specific policies about how we use third-party dependencies from npm, for example, and we’re not pulling directly from npm but from our own registry for our vetted JavaScript dependencies. Similarly, my previous employer, Olo, had private registries for both npm and Nuget packages for internal code shared across multiple projects in the organization. This is *very* normal… and Cargo hasn’t had first-tier support for it until Rust 1.34. You’ve been able to work around it with Git URLs or by pulling down source code locally and using paths to map things in your `Cargo.toml`, but neither of these were great, and they definitely weren’t viable approaches for large engineering teams like my own! Rust 1.34 ships with really *nice* support for alternative registries. You just add a `[registries]` section to your `Cargo.toml` which points to the URL for your alternative registry, and then when you add a dependency you specify both the version and the registry to use. You can now also use a `--registry` argument when publishing or logging into a registry, and there are some docs about how to run a registry. This is one of those changes that has been a long time coming, in part because there wa so much to do last year for the 2018 Edition release… but also in part because it’s a thing the teams involved wanted to get *right* as much as possible, because it’s really important. And now that it’s out there, it’s that much easier for large or particularly security-conscious organizations to adopt Rust, and that’s a big win! I’m excited to see where it goes from here! ## Conclusion Thanks as always to this month’s $10-or-more sponsors: - Evan Stoll - Martin Heuschober - Soren Bramer Schmidt - Ramon Buckland - Ryan Osial - Behnam Esfahbod - Rob Tsuk - Oladapo Fadeyi - Andrew Dirksen - Embark Studios - Jason Bowen - Chip - John Rudnick - David Carroll - Anthony Deschamps - Nathan Sculli - Michael Mc Donnell - Nick Gideo - Raph Levien - Bryan Stitt - Zach Peters - Matt Rudder - Arun Kulshreshtha - James Hagans II - Adam Green - Daniel Bornkessel (April only) - Scott Moeller - Jerome Froelich - Jeff May - Dan Abrams - Jonathan Knapp - Daniel Mason - Nick Stevens - Cristian Paul - Brian McCallister - Alexander Payne - Peter Tillemans - Daniel Collin - Dominic Cooney - Paul Naranja - Oluseyi Sonaiya - Graham Wihlidal - Jako Danar - Nicolas Pochet - Johan Andersson - Joseph Schrag - Benjamin Manns You can sponsor the show at patreon.com/newrustacean or via other services listed on the show website, . There, you’ll also find show notes, including links to things I talk about, scripts, code samples, and interview transcripts. The notes for *this* episode are at . Please recommend the show to others if you like it, whether in person, via your podcast directory, or in various media online! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending men an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/news/rust-1.35.md ================================================ # News: Rust 1.35 ## Intro Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is a news episode for Rust 1.35. ## Sponsor: Parity Before we dive in, Parity is back sponsoring the show—because they want to hire you to come work in Rust with them! Parity is advancing the state of the art in decentralized technology, and they’re using Rust to do it, leaning hard on its trifecta of performance, reliability, and productivity. They're building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Two of the larger projects they're working on are: Substrate, a framework for building blockchains, and Polkadot, a platform leveraging blockchain tech for scaling and interoperability in decentralized systems. If that sounds interesting, check out their jobs at ! ## 4 years since 1.0 The first bit of news I want to touch on—and I’ll have a little more to say about this in the *next* episode—is that two weeks ago was the fourth anniversary of Rust’s hitting 1.0! It’s kind of amazing that it’s been that long, and an incredible amount has happened along the way. If you go back and look at what Rust 1.0 looked like—the state of the ecosystem, the state of the standard library, even the language itself—it’s an amazing change over that period of time. ## Rust 1.34 point releases Next, I thought it important to mention two point releases in the 1.34 cycle: - **1.34.1** fixed two issues in Clippy. As you may recall from my comments in my discussion of Rust 1.31 and the 2018 Edition, Clippy is now an official Rust tool with the same Semantic Versioning compatibility guarantees as Rust itself. Unfortunately, 1.34.0 saw a few bugs make it into Clippy—two false positives and one panic when checking macro behaviors. Not a *huge* deal, but they shipped a fix for it anyway, which I appreciate! - **1.34.2** was substantially more serious: it was a fix for a security issue. You may recall from my discussion of Rust 1.34.0 that there was a newly-stabilized `Error:type_id` method. A careful Rustacean, Sean MacArthur, identified that this exposed a security hole. The *default* implementation was safe… but it was possible to return the wrong type when implementing the method yourself. And if you did that, you’d have a situation where Rust would treat the item as the wrong type, which can lead to very serious memory unsafety. For example: if the type was actually a `u8` and your returned a `Vec` instead, Rust would think you had a valid `Vec`… and if you started performing operations on it, like calling `my_vec.push(42)`, well, now you’d be scribbling over memory that didn’t belong to you! 1.34.2 therefore *destabilized* the feature entirely. There’s [an ongoing discussion][Issue #60784] about what to do with the feature, since it has existed since 1.0… just on nightly… and has been unsafe that whole time. (It’s just that now is the first time somebody caught the unsafety!) [Issue #60784]: https://github.com/rust-lang/rust/issues/60784 ## Rust 1.35 All right, so let’s dig into what’s new in Rust in 1.35! This is a fairly small release… which is actually *normal* for Rust, after all! It’s just that the past several months have been jam-packed with the lead-up to the 2018 Edition and a number of other major features landing. 1.35 isn’t one of those release… but it’s a good one nonetheless! I talked in episode e031 about how you can expose Rust libraries as dynamically-linkable, C ABI-exposing libraries for other tools to use. Rust 1.35 adds a flag to Cargo, `rustc-dylib-link-arg`, to make it easier to get some of the nitty-gritty details of building a library like that right: specifically, things like setting the version for the shared library or the runtime path for where to find it. Not a thing you’re going to do most of the time, but if you’re deep in the kinds of weeds we were talking about and need to build a dynamic library on Linux or macOS… you may just be happy this exists! There are a few new targets to build against… most interestingly, including a `wasm32-unknown-wasi` target. [WASI] is the recently proposed and rapidly developing WebAssembly System Interface. WASI is one of several recently-announced pieces of the WebAssembly story which start to capitalize on the promise for WebAssembly to be not just a way of targeting browsers for high-performance code, but a useful, safe (because it’s sandboxed!) cross-platform compilation target… for lots of languages, though of course at the moment Rust is really the language driving the effort forward. WASI supplies an API to do *systems programming*: sockets, file system operations, time, you name it… but with all the safety constraints (sandboxing, for example) that are inherent in the WebAssembly programming model. It’s early, but it’s possible that this (along with a number of other efforts) will represent a sea change in the safety and reliability of systems programming… which we desperately need! If you’re interested in hearing more about WASI, I’ve linked to [an episode of the really excellent podcast The Bike Shed][bikeshed #195] in the show notes, where host Chris Toomey talked with Lin Clark and Till Schneidereit from Mozilla about a *bunch* of things, including WASI. And as of Rust 1.35, Rust can now target it natively (on nightly)! Now, there’s a lot missing in the standard library when targeting WASI, as you’d expect from something this early on—WASI itself is immature enough that everyone is figuring out the best way for the implementations to work! I find this incredibly cool nonetheless, and will be watching it very closely. [WASI]: https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-intro.md [bikeshed #195]: http://bikeshed.fm/195 In terms of language features and library stabilizations, there are a handful of nice improvements: - The `dbg!` macro can now be called with no args at all. “But what would that even print out,” you ask? “The file and line where you put it,” I say! A handy tool in the debug-printing toolbox. One place you might use this: watching how multithreaded or asynchronous operations interleave. - The expanded `Debug` format—which I always forget about; you type it `{:#?}`, and it’s what the `dbg!` macro uses—now includes a comma after the final struct field… to make it match the idiomatic output in modern Rust. A hilariously tiny change, and I kind of love it. - `Option` got a `copied` method, which copies an `Option<&T>` to an `Option`. As you’d expect, `T` here has to implement `Copy` for this to work; it’s a nice little ergonomics win when it’s available, though, and there’s no particularly nice way to write it in Rust without this. You’d have to do something like: ```rust let copied = some_option.map(|val| { let new_val = val; new_val }); ``` Now you can just write: ```rust let copied = some_option.copied(); ``` Handy! As always, of course, you should read [the full release notes][1.35], because there are other pieces that landed here, some of which may be particularly interesting to you! [1.35]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1350-2019-05-23 ## Final `async`/`await` syntax Before we wrap up today, I also want to talk about the final `async`/`await` syntax, which *should* be stabilizing in Rust 1.37. The development of the primitives for ergonomic, asynchronous code in Rust has been a long, slow path—which is appropriate in a lot of ways; getting this right in a way that maps to Rust’s commitment to zero-cost abstractions *and* usability has been an incredibly hard task. If I’m honest, I still don’t have my head all the way around the features here, and I think it’ll take me some serious digging before I do! The gist is this, though: there is a *library*, `futures`, which provides a number of types and functions in support of them for asynchronous programming—from the eponymous `Future` type, a single value which eventually resolves (or not!), very much like a `Promise` in JavaScript or a C# `Task`; to stream types, which represent a *series* of values over time; to tools for asynchronous I/O or asynchronous execution of operations. You can check out [the API docs][futures-rs] for details [futures-rs]: https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.16/futures/ All of this was developed against nightly Rust over the past several years—and I do mean *several years*; the earliest phases of this work began in 2016! For much of that time, the work has been done using *macros*: the `#[async]` attribute to specify when a given function has async behavior happening in it and to invoke an asynchronous function with the `await!` macro-rules style macro. However, now that the story around the library and the design of its integration into Rust as a core primitive is stabilizing, it’s time to land a dedicated syntax. There’s been an *enormous* amount of discussion about this—an amount I’ve found exhausting as a casual observer; I can’t imagine how taxing it must have been for everyone involved. It turns out that language syntax provokes strong feelings from people. Who’d have thought, right? You may be wondering, even before we get into what the dedicated syntax *is*, why we need it, given that we’ve gotten by through the whole design period with macros thus far. The basic answer is: tooling! While macros can be made to work, and fairly well, it is difficult to get them to provide good diagnostic feedback during the compiler operations. This means that the experience of working with asynchronous code using the macros always feels second class. You’ve probably run into this yourself if you’ve used crates which are heavy on macros: even when the authors are doing a really good job, it can be much harder to figure out why something isn’t lining up—*which* types are wrong, and *how*, for example—than when you’re *not* using macros. For a feature as core to the future of the language as async and await, it’s important that make these things genuinely first class. Let’s start with `async` functions: you write them `async fn` with a normal function signature and—and this is the important bit—the return type as if it were *not* a normal function signature. So if you have a function which will ultimately resolve as a type which implements the `std::future::Future` trait, with the associated `Output` type being a `Result`, you’d write: ```rust async fn my_neat_thing() -> Result { // and then the body of the function } ``` One reason for *this* choice is that it’s often *very* difficult—borderline impossible—to write out the fully resolved type of some complicated chain of futures. While futures are *like* JavaScript promises in some ways, Rust’s commitment to zero-cost abstractions means the language requires the type system to do a *lot* more work, rather than just throwing more memory allocation at it via allocations (which is basically how JavaScript handles it). Using the `async` keyword for this transformation means that you as an author can see that it’s a function which has this special asynchronous handling behavior, and see what it will resolve to, without needing to figure out how to write that complicated chain of types yourself. The other half of this is the `await` keyword. It looks almost certain to end up in what looks like field access position. That is, if you have some method which returns a future, you’d indicate that you’re then awaiting its result (not immediately chaining it into a new future via some combinator or other) by writing `.await` after the invocation. So you might have a whole function which looks something like: ```rust async fn neato() -> Result, String> { let doubled = get_some_i32s() .await? .iter() .map(|i| i * 2) .collect(); Ok(values) } ``` That invokes `some_other_async_fn_with_i32_in_a_result`, awaits the result with the `.await`, invokes the `?` operator to early-return if it’s an `Err`, then maps over the `Vec` which that function handed back, and returns a collected version of that as an `Ok` variant. Note that it *is* still returning a future in the end, and the compiler will be able to give us appropriate feedback about the types along the way… but it is a smooth experience. I was a bit surprised initially by the choice of this position, instead of the `await some_other_async_fn_with_i32_in_a_result()` you’d expect coming from JavaScript or C♯. However, I came around fairly quickly when folks pointed out that other languages which use that position are *statement*-oriented. Rust builds everything out of expressions—it’s one of the things I love about it—and encourages chaining those expressions together. Idiomatic Rust also uses the `?` operator for short-circuiting when there’s an early error a *lot*. The combination of those two factors means you’d end up writing something like `(await some_fn())?` a *lot* unless there were a special case rule around the combination of `await` and `?`, and that would be both pretty surprising and also have some strange side effects. As much as it initially seemed weird, I’ve already gotten pretty used to it and it makes a lot of sense. (Also, it’s far from the only thing that happens in field access position which is *very* syntax sugary. Even method invocation does some pretty fancy things there to get `self` as the right kind of thing… for example, when you take `Box<&mut self>`, which you can do!) There’s a *lot* more discussion around this, which I’ve [linked][so-long-omg] in the show notes, and it’s technically getting finalized in today’s language team meeting, so this *might* change… but it looks like this is how it’s going to land. [so-long-omg]: https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021 I’m excited by this, in any case. In just a few weeks, we’ll be able to write async/await code on stable Rust, and that will, I think, be another big leap forward in the places where Rust is a viable and indeed *excellent* choice. ## Outro And that’s a wrap on this news episode. The next episode will be out on Monday… and it’s a special one. Keep your eyes on your podcast feeds! ### Patreon Sponsors Thanks as always to this month’s $10-or-more sponsors: - Arun Kulshreshtha - Matt Rudder - Soren Bramer Schmidt - Dan Abrams - Oluseyi Sonaiya - Anthony Deschamps - Evan Stoll - Nick Gideo - Dominic Cooney - Embark Studios - Scott Moeller - Benjamin Manns - Daniel Mason - Jonathan Knapp - Nick Stevens - Jeff May - Behnam Esfahbod - Johan Andersson - Nathan Sculli - James Hagans II - John Rudnick - Zach Peters - Chip - Jerome Froelich - Andrew Dirksen - Joseph Schrag - Brian McCallister - Bryan Stitt - Raph Levien - Nicolas Pochet - Daniel Bornkessel (April only) - Ryan Osial - Jason Bowen - Jako Danar - Michael Mc Donnell - Adam Green - Alexander Payne - Rob Tsuk - David Carroll - Ramon Buckland - Martin Heuschober - Peter Tillemans - Paul Naranja - Graham Wihlidal - Ola Fadeyi - Cristian Paul - Daniel Collin ### Show info You can sponsor the show at patreon.com/newrustacean or via other services listed on the show website, . There, you’ll also find show notes, including links to things I talk about, scripts, code samples, and interview transcripts. The notes for *this* episode are at . Please recommend the show to others if you like it, whether in person, via your podcast directory, or in various media online! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending men an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/news/rust_1_29_1_30.md ================================================ # Rust 1.29 and 1.30 Hello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust Programming language and the people who use it. This is a news episode, for Rust 1.29 and 1.30. ## Sponsor: Parity Technologies Parity Technologies is here sponsoring another episode! Parity is advancing the state of the art in decentralized technology. Their flagship software is the Parity Ethereum client, but they're also building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Their next big project is Polkadot, a platform leveraging blockchain tech for scaling and interop in decentralized systems. Parity uses Rust for its trifecta of safety, speed, and correctness—and they’re still hiring Rust developers! Check out their jobs at paritytech.io/jobs. Thanks again to Parity for sponsoring the show! ## [Rust 1.29](https://blog.rust-lang.org/2018/09/13/Rust-1.29.html) Changes Rust 1.29 was a relatively small release, because Rust 1.30 was and 1.31 is going to be really *big* releases. (If you’re wondering why there is a combined episode for these: that plus the burnout I talked about was enough for me to say *pass*.) But there were a *couple* things, so let’s talk about those before we dive into the larger changes around 1.30 and the 1.31 beta! The biggest feature in 1.29 was the new `cargo fix` command in Cargo. `cargo fix` is a general-purpose tool to fix a certain set of compiler warnings *for you*. If you’ve ever looked at one of Rust’s extremely friendly and detailed compiler warnings and thought, “Okay, Rust, if you’re so smart and can tell me exactly what I should change here, why don’t you just *fix that for me*?” well, `cargo fix` is what you’ve been looking for! Of course, it’s important for this to be relatively conservative: the tool should only fix things where it’s 100% sure that the fix is correct. The new compiler API that drives this will expand over time as new sure-to-be-right fixes land, but for today it will only fix a few things. `cargo fix`, being this general-purpose tool, is something people have dreamed about for a long time, but it landed when it did because we need it for the 2018 Edition release to be successful. And that takes us to a special flag you can pass to `cargo fix`: `--edition`. This checks your code against the *current* and *next* editions of the compiler, and helps you get the code into a state where it works with both. If it can safely update your code automatically for you, it will; otherwise, it’ll print warnings with instructions about how to proceed. I mentioned `cargo fix` in an earlier episode when the first beta of the feature was released, but it’s now on stable Rust – and in my experience so far, it works really well! I converted my (now active again!) Lightning static site generator project using it and it was a piece of cake. Mind: that’s a whopping thousand lines of Rust so far, so it’s very, very small in the grand scheme of things. But! `cargo fix` just worked, and using it was a great experience. Rust 1.29 also shipped a preview of the `cargo clippy` command. Clippy is a tool for *linting* your code – named after the old (silly, annoying) Clippy tool in Microsoft Office back in the 90s: the one that would put up prompts on your screen like “It looks like you’re composing a letter; would you like help with that?” In Rust, Clippy suggests best practices – things that aren’t at the level of compiler errors, but which are likely to make your code more maintainable over time. `cargo clippy` brings this to a first-class integration with the language. It’s still in preview, but you can check it out now. There were also some small stabilizations in the standard library and a few new targets added to the compiler here – as always, you should look at the [full release notes](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1290-2018-09-13) to see all the details of the release, and as always they’re linked in the show notes – but most of the focus was on the pieces landing in 1.30 and 1.31, so let’s talk about those! ## [Rust 1.30](https://blog.rust-lang.org/2018/10/25/Rust-1.30.0.html) Changes Rust 1.30 dropped a *buuuunch* of changes on us. The biggest two are stabilization of procedural macros and new features for how paths are handled for crates and items within them. ### Procedural Macros Procedural macro stabilization has been a long-desired feature for Rust, because procedural macros let you do some really amazing compile-time code generation. But they’ve been limited to nightly for a long, long time. Back in the Rust 1.15 release, a subset of procedural macros were stabilized. (I talked about those a bit in the [Crates You Should Know: Serde](https://newrustacean.com/show_notes/cysk/serde/index.html) and [Traits Deep Dive Part I](https://newrustacean.com/show_notes/e023/index.html) episodes, both linked in the show notes.) However, those were only part of the story… and the rest of the story landed in Rust 1.30. This brings two new kinds of macros we can write: 1. We now have the ability to write our own attributes. Recall that custom derive macros were limited to macros which could run in the context of the compiler’s existing `#[derive]` macro. That limitation is now lifted. This opens the door for things like Rocket’s routing attribute macros to work on stable. 2. We can write function-style macros, which are *like* macros-by-example (which we covered a bit back in [episode 10](https://newrustacean.com/show_notes/e010/index.html)), except that they have the full power of procedural macros: that is, full access to all the tokens within the body of the invocation and the ability to generate all the desired code we want. Remember that macros by example don’t have access to the compiler, they’re just smart syntax substitutions. Procedural macros get to actually run the compiler themselves for code-gen purposes, and are thus strictly (and profoundly) more powerful. These two features being stabilized mean a lot of things that previously only worked on nightly are available for everyone to use on stable Rust today. That’s a big win! Finally, one of my longest standing annoyances got fixed: you can now reference macros the same way you reference… everything else. Historically you had to write the `#[macro_use]` attribute on the `extern crate` reference for the crate where you wanted to pull in a macro… but you didn’t specify the name of the macro there! It’s always been a bit of a weird outlier. Now, you `use` macros just like you do anything else. So, for example, to pull in Diesel’s `not_none!` macro, you would just write `use diesel::not_none;`… and drop the `#[macro_use]` entirely. This is a really nice win for consistency throughout the language. ### Paths That also takes us right into the other *huge* (but still backwards compatible!) change in Rust 1.30: module paths got a really nice set of improvements. It’s no secret that understanding Rust’s module path system has been a serious learning hurdle for a lot of people. There are a lot of reasons for this, including just the ways it is *different* from other systems—but the biggest is that the module system we shipped with Rust 1.0 works one way in the root of the main module (whether that’s `lib.rs` or `main.rs`) but does *not* work that way everywhere else. Those differences (and many other confusions) flowed out of the way that the actual rules for paths worked to make them items like everything else—the kind of thing that was *super* elegant but also, in practice, *super* confusing. The difference had to do with what `extern crate` did in the context of the crate root. If you wrote `extern crate regex`, then in your `main` function or somewhere in that `lib.rs` file, you could reference anything on `regex` directly—for example, by writing `regex::Regex::new()`. However, in the *rest* of your crate, even just in a nested module written inline in that same file, you explicitly had to `use regex;` to make that invocation work, because the namespace—the lookup context—had changed from the root. This confused *basically everyone*. So Rust 1.30 brings a big fix (and the 2018 Edition yet more fixes; more on that in the future). Here’s how the fix works: 1. You don’t need `extern crate` anymore, at all, ever. You can simply refer to crates’ paths by their crate name and the Rust compiler does the right thing and looks them up for you. So you can `use serde::Deserialize;` without needing to write `extern crate serde;` first. 2. You can name things from your crate root with the new use of the `crate` keyword. It used to be that paths after the `use` keyword started from the root, but paths in an item context (like a method name) used the local path instead. You may have seen a reference with `::some_path` before; this was the old, rather ugly way to get back to the crate root to start a path. That style has been replaced by the new, much clearer `crate::some_path` syntax, and as a result paths can now work consistently *wherever* you use them, so long as you include the `crate` keyword where you should. Running the aforementioned `cargo fix --edition` will do this for you, as an aside: because Rust 2018 *requires* the new style (whereas Rust 2015 simply *supports* it). In my experience, switching to this new system was incredibly easy. It was a case of things just working the way they felt like they *always* should have worked. ### Grab bag Finally for 1.31, there were a number of other, smaller features worth mentioning in this release: - There’s now syntax to let you use identifiers as keywords: you write `r#` in front the keyword. This is not something you’ll normally see *often*… unless you’re using one of the new keywords from Rust 2018: `async` and `await` for use with Futures as they standardize, and `try` to replace the current `do catch` blocks, which are sugar for special handling around things like `Result` which implement the `Try` trait. You may have code in Rust 2015 that uses `try`, or `async` or `await` as a name for something, because they weren’t previously keywords. You can keep those in Rust 2018 code, by writing them (for example) `r#async`. (I *believe* `cargo fix --edition` will handle this for you.) - You can now build `no_std` *applications*. Turns out that you’ve been able to write `no_std` *libraries* for a long time (since Rust 1.6 three years ago!), but not *applications*. You had to call `no_std` libraries from… not Rust. There’s now support for telling the system how to implement panics when the standard library doesn’t exist, via a new compiler attribute, `#[panic_handler]` which you apply to a function which can implement application behavior for panics. This is a big deal for contexts like embedded software or WebAssembly! - Cargo got a progress bar! It tells you roughly how far along in the process of doing a build you are. Just a nice little detail. - There are a bunch of handy little convenience values for IP address lookups: `Ipv4Addr::LOCALHOST` and `Ipv6::LOCALHOST`, for example. These are tiny, but they’re handy for making sure you don’t typo something where it matters! And there are more; I’ve linked directly to [the full release notes for 1.30](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1300-2018-10-25) in the show notes as well. ## Rust 1.31 – The Rust 2018 Edition Beta! The other *really* big news is that the Rust 2018 edition is now *in the beta channel*. I’m not actually going to talk about the features, because I’m planning to do a series of episodes celebrating the release by digging into the biggest new features—they warrant that level of explanation. For today’s purposes, it’s enough to know in *most* cases that it’s nearly here, and you can *and should* test it out. To install the beta, you can just do `rustup update beta`. Then you can either use it by doing `cargo +beta build` or `cargo +beta run` with your app, or by setting is as an override for a given project with the `rustup override` command. I say this often, but I’ll reiterate as we’re coming into the home stretch: *please* test your projects and file any bugs that come up! This is a pretty big deal for Rust, and your bug reports or comments on unclear documentation (for the edition guide, for example) could be a really big deal for someone coming in to check out Rust either for the first time as the news hits, or *again* to see how it has changed. ## Closing That’s all for today. The episode on `unsafe` is coming together nicely, and I should be able to finish drafting it (and I might even be able to record it) over my Thanksgiving holiday! And of course I’m lining up a *ton* of coverage of the Rust 1.31 / 2018 Edition release. Thanks, as always, to everyone who sponsors the show! This month’s $10-or-more sponsors included: - Scott Moeller - Oluseyi Sonaiya - Anthony Deschamps - Ramon Buckland - Paul Naranja - James Hagans II - Nick Stevens - Steffen Loan Sunde - Alexander Payne - Behnam Esfahbod - Graham Wihlidal - Nicolas Pochet - Martin Heuschober - Nick Gideo - Bryce Johnston - Daniel Collin - Rob Tsuk - Dan Abrams - John Rudnick - Matt Rudder - Jonathan Knapp - Jerome Froelick - Peter Tillemans - Chris Palmer - Nathan Sculli - Bryan Stitt - Joseph Marhee - Michael Mc Donnell - Ryan Osial - Jako Danar - Chip - Adam Green - Raph Levien - Daniel Mason If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, send a one-off at any of a number of other services listed at newrustacean.com, or get in touch directly. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for *this* episode at . If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/rbr_2017/andrew-hobden.md ================================================ ================================================ FILE: docs/rbr_2017/anthony-deschamps.md ================================================ # Anthony Deschamps **Chris:** hello! Can you tell me your name and a little bit about yourself? **Anthony:** My name is Anthony Deschamps, I, um, I’m a software developer, I work in Automotive. **Chris:** Oh! Very interesting. Long-time listeners will recognize Anthony’s name as a sponsor of the show; thank you for sponsoring the show! **Anthony:** You’re welcome! **Chris:** So, what got you into Rust? **Anthony:** I’ve talked about this earlier; I actually can’t remember how I first came across it. Um, I remember my friends being excited about it and looking at it at some point, um, but what really hooked me is that I have a huge amount of respect for C+ +, uh, it was one of my first languages, and to me, Rust feels like C+ + with decades of learned lessons. If we have a clean slate, and what you can do with a fresh start. **Chris:** Yeah. How long - do you remember roughly, obviously you don’t remember exactly when, but - do you remember roughly how long...pre 1.0, post 1.0? **Anthony:** Uh, probably about a year ago, so, somewhere after 1.10 or roundabouts. **Chris:** Okay. Very good. What has your experience of learning Rust been like? Good, bad, ugly? **Anthony:** Um, it’s made my C+ + better. **Chris:** Yeah. **Anthony:** Everything thing that I struggled with in Rust was really just a lesson for what I could be doing better in other places. **Chris:** What are you using Rust for presently? Are you able to use it at work at all, or is it side projects entirely, still? **Anthony:** So, a combination of hobby projects, uh, when I have time. And, a little bit at work. It’s one of those things where it is a little bit of a risk, a newer thing, so it’s been nice to try it out on some small things, see how it goes, and realize that I do like it and get excited about hoping to use it more. **Chris:** Yeah. What kind of side projects have you been able to do? **Anthony:** Um, when I get around to strapping a Raspberry Pi to a balloon and sending it up to the stratosphere to take some photos, that’ll be in Rust. **Chris:** That’s awesome. **Anthony:** I also like to play around with arduinos, and LEDs are fun, and I’m using a little bit of Rust there. **Chris:** Cool. Is there anything in particular that’s caught your attention either with this conference or with the Rust community in general? **Anthony:** The most exciting thing to me is meeting the people who are making the things that I enjoy using. Uh, it seems obvious when you really think about it, but, um, the things that you use are not made by some...cloud, or void, or they don’t just come out of nowhere, they’re made from real people, who really enjoy working on what they’re doing, and are really excited to talk to you about it. **Chris:** I share that sentiment deeply. Thank you for your time! **Anthony:** Well, thank you so much for the podcast. I really enjoy it. **Chris:** My pleasure, and absolutely awesome, speaking of meeting people in person, it’s great to meet you in person! **Anthony:** I agree. Thank you so much. **Chris:** Thank you! ================================================ FILE: docs/rbr_2017/arun-kulshreshtha.md ================================================ # Arun Kulshreshtha **Chris:** Hi, can you tell us your name and where you work and how you got into Rust? **Arun:** Sure. My name is Arun Kolshreshthra. I’m a software engineer at Facebook, and that’s actually how I got into Rust. Um, when I joined Facebook, fresh out of college, um, there was a new Rust project - a new Mercurial server being written in Rust there. I joined Facebook’s source control team and have been working on that server ever since the middle of last year. It’s been really fun, and I’ve been learning a lot about the language. **Chris:** Sweet! Mercurial. No one knows this, probably, other than close friends of mine, but I really wish Mercurial had won instead of Git. So, I was really excited to see people pushing on that. Uh, how long - you said about a year and a half that you’ve been writing Rust? **Arun:** Yeah, that’s about right. **Chris:** What has been the best or most enjoyable part of that so far? **Arun:** Well, what I’ve really enjoyed is being able to write systems programming, like, just doing systems programming, in a language that has things like algebraic data types and other features from the functional programming world. I myself am coming from a mixed background where I both did a lot of systems programming and a lot of functional programming in languages like Haskell in college, and the functional programming stuff really appealed to me, and I always wish C and C+ + had those features, so it’s really great getting to use them every day in my systems work. **Chris:** That’s awesome. So, I know that’s an open source code base - how big is it now? **Arun:** How big is the Mononoke project, which is the uh, source control server? I’m not actually sure what the actual lines of code are because I don’t keep up with our git hub repo from day to day, um, not everything is open source unfortunately, but a good chunk of it - the majority of it - is on Github. I’d say, you know, definitely several thousand lines, probably tens of thousands of lines, but don’t quote me on that, because I don’t actually know. But if you search on Github you’ll find the repo and you can find out. **Chris:** What, if any, have been pain points for you along the way with Rust? **Arun:** So the biggest pain point has probably been, like, Facebook is definitely a C+ + shop, as far as the back end is concerned, so all of the existing libraries and APIs are all designed with C+ + in mind. One of my jobs has been to write bindings to those libraries from Rust, and unfortunately, while the binding situation in Rust is actually not bad, with tools like bindgen to help automatically generate those bindings, it turns out when you’re using really advanced C+ + features, like C+ + 14, and maybe even C+ + 17 features - because Facebook always has to be on the bleeding edge after all - bindgen falls over, and you find yourself writing all these wrappers and shims to get everything to work, and that is a bit of a pain. I wish I didn’t have to do that on a near daily basis, but that is my life right now. But, the pain’s worth it to get to use Rust. **Chris:** That’s, that’s fair, I think! Uh, is there anything else - any particular standouts - of your time so far here at Rust Belt Rust, or that you’re looking forward to? **Arun:** Just interacting with the community members here at Rust Belt Rust has been amazing. Uh, I was also at Rust Conf for earlier this year, and I found that the community is extremely approachable and welcoming. I was really worried, like, I’m a new grad; I barely have any industry experience. Hell, I don’t even know what I’m talking about some of the time. Like, will I fit in? But, like, I can talk to, like, some of the maintainers of, like, key crates, you know? They’ll have a technical conversation with me and, like, give me pointers and stuff, and that’s really awesome. **Chris:** Awesome. Thanks so much for your time, Arun. **Arun:** Yeah, thank you! ================================================ FILE: docs/rbr_2017/ben-striegel.md ================================================ # Ben Striegel C: Hello! B: Hello! C: Can you tell me your name and a little about yourself? B: Ben Striegel, I currently work at a machine shop at Harvard, I have been using Rust for about six years now. So if you had, like, a resume, company is like, “I demand at least five years experience in Rust,” and I am one of the, like, ten people in the world who can actually say, “Yes.” C: How in the world did you get into Rust in 2011? B: I don’t really remember...it’s kind of hazy in my mind when I first found it, but it was kind of...hm...I was at my job, and part of my job, which is a very long story - too long for now - was kind of like exploring new languages to try and rewrite a system that I was hired to rewrite, and somehow I found Rust, and at this job I was kind of like the only person there who cared about new technologies or becoming, independently, a better programmer, and so, kind of like by looking in the Rust IRC channel, which was the like, the entire community was, like, thirty people back then, in an IRC channel! I say this (garbled - something about my alma mater) - but I learned more in one year of looking in that channel than in four years of my CS degree, and it was an incredible experience to actually witness this language being made, a very early days, very primordial, and to this day I still kind of like, you know, I am one of the few people who can give firsthand talks on crazy old stuff that was in the language - vague, immature Rust historian that I am - and so I kind of like, became, like, as a lurker, who was there every day reading every scroll back, kind of became the guy, who was like, you know, someone who hadn’t been there for a week came back and like, it’s been a week since I worked on my Rust code, and it breaks - obviously, because that’s how it was back then, so I was the guy who would tell you how to update your code, and every “I’m new to the language, teach me...” I became like their teacher in that sense. So, yeah. C: That’s awesome. So what is currently exciting and what kinds of things are you looking forward to in Rust? B: Currently exciting? I am excited that we have maintained stability for two years now, and trying to expand on the platform that we created with 1.0. I’m excited for compiler speed improvements. I think it’s kind of one of the bigger things, like the worrying things in industry, where it’s like, “Well, you’re better than C+ + broadly, but it’s not like a very high bar to clear.” So, other than that, I think mostly my concern is - so, before 1.0, saying as someone who was kind of like around for a long time, we had this vision of several things that Rust still hasn’t quite gotten around to having that stable, so, like, ASM being one of those things, and a few things, like Infiltrate (sp?), coming soon, hopefully, Conts Generics (sp?), coming soon, and maybe the box syntax placement new (sp?), and once those are in, it’ll feel like the language we had envisioned seven years ago - seven years ago as of next year, or whatever - is finally here, and come to pass. C: It has arrived! B: It’s arrived! It’s finally here! Congratulations! C: Awesome. What are pain points that you run into regularly? B: Pain points. Well, one thing that they mentioned today here at Rust Belt Rust, in a keynote, was the match ergonomics thing, where I’m always like, star over here, ref over here, should there be an ampersand over here, should we be using pattern matching, should I like (unintelligible - something about a match statement)? That kind of thing. That’s actually going to be lovely. I love that. I’m looking forward to also question mark in main. C: Yes. B: That RFC? Because I mean, like, if your doing examples like me, as a teacher, you don’t want to worry about having main then call into a function that returns a result properly, you want to be able to use the question mark, and “(unintelligible - something about wraps)”. “Well, it wouldn’t be there in your actual code, I’m just kind of trying to...” That sort of thing. So, that’s a great RFC I’m looking forward to. C: Awesome. Anything else you want to call out about Rust, Rust Belt Rust, the community? B: I love Rust Belt Rust, because I’m from Pittsburgh, and so I’m happy to see that we are doing this kind of thing every year...like helping...but we’re doing our part to teach folks who are still around here to do cool things. C: Thanks so much for talking to me! B: No problem, Chris, thank you for having me. C: My pleasure. ================================================ FILE: docs/rbr_2017/colin-dean.md ================================================ Read the episode transcript! # Colin Dean **Chris:** Can you tell me your name? **Colin:** I am Colin Dean. **Chris:** Hi, Colin. Thanks for sitting down with me. How did you get into Rust? **Colin:** Uh, so, I used to work with Carol Nichols-Goulding who is one of the - I think she’s now on the Rust core team. She introduced me to Rust a few years ago, I’ve held several meet-ups with Rust, and I, just in the last year or so, started using Rust at work. **Chris:** Awesome. Can you tell me where you work? **Colin:** Arcadia Healthcare Solutions, where I’m director of software engineering. **Chris:** Awesome. What kind of cool things are you getting up to with Rust at this point? **Colin:** So our first big project is actually a very small Rust program that we’re using to act as a supervisor for a much larger system. We needed something that was really reliable, could do concurrent code, and most importantly it was going to be native binary. So we eliminated a lot of contenders for that, kind of arrived at C or C+ +, and then I was like, “Oh, hell no, we’re gonna use Rust.” **Chris:** Hahaha! I can understand. What are you excited about in the next - I don’t know - six months, a year...what kind of things do you have on your radar for Rust work? **Colin:** Probably the two big ones are shipping this product that will soon be responsible for supervising petabytes worth of transfer of health record data, and, um, contributing a whole lot to the Rust ecosystem. I’ve hired somebody who works on crates and she’ll be doing a lot of Rust stuff and kind of owning it. It’s her first big job, well, her first job, period - at least her first programming job - and she’ll be in charge of this little Rust component and, so shipping that’s really important, and then figuring out how we want to do all the continuous integration, how we want to support it when things go wrong...those are skills that I’ll be learning, she’ll be learning, and contributing back to the Rust ecosystem, where we’ll be shipping on Windows, so Rust is not necessarily Windows-super-friendly yet, and where we find gaps, we’re going to be contributing the code back to the community. **Chris:** That sounds awesome, doubly so because you’re hiring, or you’ve hired, one person and you guys are actually using Rust. What have been big wins, and what are perhaps any pain points so far with Rust? **Colin:** So, um, we haven’t had any big wins yet; the system is still very new, it’s still less than five hundred lines of code. Our probably biggest pain point right now is how to do CI on Windows. Um, I’m kind of used to a development world where I’ve got containers that have the entire build everything, and I kind of push it up, and it just works. Think, like, Travis, or Jenkins on steroids, and I don’t have that where we are right now. Our Jenkins installation has ten jobs in it, and, uh, they all do stuff with Gradle for a Java app that another team uses, so I’m kind of starting from nothing and trying to figure out how do I do this. There are some other...I think Appveyor does, like, Windows builds, so we’re looking at that, but we have some requirements that might need to keep that in-house, and so we’ll have to sort through that, see what exactly we want to do. Um, but the CI story is probably the hard part. I’m also finding some interesting problems with kind of an immaturity of documentation, like the Rust docs are great, but there’s some parts of it that are - especially on crates, because so much of the library is crates - that they’re just not very well documented. So, I’m finding myself contributing a little bit here and there to documentation. I put up a couple of pull requests just today, fixing some docs. So, I think that’s gonna continue to be a thing, and I know that they - the Rust team - is doing a lot to try to push people to improve how they document their code, because the Rust team knows how much of the Rust ecosystem is external libraries. It’s not, you know, there’s no...there’s a standard library in Rust, but it’s not a standard library in, like, in the sense of like a Java standard library where I’m kind of coming from, where there’s just everything. **Chris:** Absolutely. Thank you for talking with me. I look forward to seeing and hearing more of what Arcadia gets up to and what you get up to! **Colin:** Cool, thank you very much! ================================================ FILE: docs/rbr_2017/holden-marcsisin.md ================================================ # Holden Marcsisin C: Hello! Can you tell us your name and a little bit about yourself? H: Um, I’m Holden, I’m a student from Pittsburgh, and I go by Ospiel (sp?) on the forums and the reddit, and uh, yeah, I’ve been programming in Rust for about two years now. C: Awesome. How did you discover Rust? H: One of my friends - shortly after I had stopped programming in Java and Python just from school - I was interested in doing lower-level programming, in doing just more advanced stuff and I wasn’t aware of any other languages, so a friend of mine pointed me as just a (unintelligible)...in a chat room, one of my friends there, she pointed me towards Rust...so I started using it, I really liked it, I liked what it was doing with the language and I just kept using it for the past two years. C: Awesome. What kinds of things have you built with it or are you building with it at this point? H: For the most part I’ve done, uh, like, graphical stuff and user interface stuff, because I feel like the Rust current user interface story is pretty lacking, and it’s missing a lot of stuff...there are libraries that exist in Rust right now, but I don’t feel like they really take advantage of the features that Rust has, and they are mostly like libraries that exist in C and C+ +, which makes sense, because, like, the biggest one - GTK - it is bindings to uh, I don’t want to say just bindings to the language, because they put a lot of work into that library, and it’s in a pretty impressive state, but I think there’s only so far you can go by binding to another language and using the existing API, so I’d like to make something in Rust that takes advantage of Rust features like traits and uh, procedural macros to make something that is really pleasant to use and couldn’t be made in another language. C: That’s a really cool ambition. What - actually, do you have a lot of background in that kind of stuff, or did picking up Rust inspire you to do that? H: Um, I don’t have a lot of background. I am interested in doing stuff with video games, and I’d like to make tooling for those games in Rust, but one of the requirements to do that is to have a user interface library to actually make the tools, so I...that’s not currently available, so I’ve just been working on that for about the past year now. I’ve been trying out various different solutions, and not all of them have worked. Right now, I’m currently about on the third iteration through and I think this is like - what I have now is something that I think I will able to get out there and publish as something I am happy with. C: That’s awesome. Are there any particular things you’d call out as successes or failures for Rust itself, or for the community, that are worth note? H: Something that I would say that is going well with Rust is - the community is super nice and welcoming - and something that I really like is that, because it’s such a new language, people are encouraging experimentation in topics and this is facilitated by stuff like crates.io which lets you easily create the new packages and publish them, and quickly swap between packages and try them out, I think that’s really important...and because this is a new language and there aren’t established solutions that’s also helping it, because people can try out new ideas and create new solutions to problems that have already existed, and actually have a chance to succeed in that, because the community is so small that people can work together...they can create something that actually has a chance at making an impact. That’s not the case with say, from what I’ve seen with JavaScript, which has a bunch of people creating libraries, but the space there is super crowded, but C and C+ + there are already established solutions that are the go-to to use and you don’t have very much reason to use anything else besides those. C: That’s a great perspective. Thanks so much for your time. H: Mm-hm. Thanks for talking to me. C: My pleasure. ================================================ FILE: docs/rbr_2017/jess-saxeter.md ================================================ # Jess Saxeter **Chris:** Hello! Can you tell us your name, and where you work or where you’re from? **Jess:** Hi, my name is Jess Saxeter. I am from Dayton, Ohio. I work at a subcontractor out there. **Chris:** Sweet. How did you get into Rust? **Jess:** I do not remember when I initially started. I stumbled across it – I don’t remember how - but it was back in the Rust 0.9 days. I remember hoping, hoping, hoping that it being 0.9 meant that there was going to be a 1.0 release shortly. It turned out to be not that far wrong, but...! **Chris:** How many releases after 0.9, or how many months after that, was it – do you remember? **Jess:** I do not remember. It was at least a year. **Chris:** Okay. So quite awhile. You’ve been around for quite awhile, then. What do you use Rust for right now? **Jess:** I actually do not use Rust in my day job; I do, however, have a hobby project of adapting the Servo (?) browser engine into a UI toolkit that is just now getting to where it might actually be compiling, if not actually doing anything, but it’s compiling! **Chris:** Compiling is a good step! What inspired you to do that? That seems like an awesome but a pretty big lift. **Jess:** What inspired me to do that is well, my day job, I write really boring line of business apps for the military, and these really boring line of business apps need really useful UI libraries in order to be able to work. If I was ever going to try to use Rust for my day job - which, it’s not going to happen in this particular day job - I would really need a good UI library, something on the order of, like, Winforms (?). Winforms is the library we use. Winforms or Zamil or something like that, and honestly the idea of marrying HTML, CSS, and Rust, just getting rid of the entirety of JavaScript and only using Rust, I find very compelling. **Chris:** Sweet. What kinds of things have been good, and maybe what kinds of things have been bad in your experience of using Rust? **Jess:** Good things - I like how strongly typed it is. I particularly like the ability to say “Give me that variable and you can’t use it ever again” in an API. It seems like the - it’s overall built to say exactly what you mean to say and have the compiler understand exactly what you mean to say - that I’ve been wanting and wanting these sort of things in my day job, in that C # does not have any notion of ownership at all - _everything_ is aliased, and I wish it wasn’t. For things that I have run into so far, not much, but I also haven’t actually gotten anything compiling yet, so... **Chris:** Fair enough. Thanks so much for your time, Jess, it’s been nice chatting with you! **Jess:** It’s been nice chatting with you; thank you! ================================================ FILE: docs/rbr_2017/master-script.md ================================================ # Rust Belt Rust: Micro-interviews Hello, I'm Chris Krycho and this is New Rustacean: a podcast about the Rust programming language and the people who use it. This is Meta Episode 2: Two Milestones. This is a micro-interview from Rust Belt Rust, October 27–28, 2017, in Columbus, Ohio. ## Outro Thanks so much to this month's $10-or-more sponsors: - Aaron Turon - Alexander Payne - Anthony Deschamps - Chris Palmer - Behnam Esfahbod - Dan Abrams - Daniel Collin - David W. Allen - Matt Rudder - Nathan Sculli - Nick Stevens - Peter Tillemans - Philipp Keller - Olaf Leidinger - Raph Levien - and Vesa Khailavirta If you're enjoying the show, please let others know about it in person or on social media, rate and review in your favorite podcast directory, or, if you're feeling extra generous, by sending some financial support for the show my way at Patreon.com/newrustacean or as a one-off via any of a number of other services I've listed on the show website: newrustacean.com. NewRustacean.com also has transcripts for all the Rust Belt Rust interviews, thanks to the hard work of my amazing wife, Jaimie Krycho. It also has show notes for every episode, and you can find scripts for most episodes at the repository on GitHub. The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com. Until next time, happy coding! ================================================ FILE: docs/rbr_2017/pete-lyons.md ================================================ # Pete Lyons **Chris:** Hello! Can you tell us your name and a little bit about yourself? **Pete:** Uh, my name is Pete Lyons, and I currently am an independent consultant focused on Node. **Chris:** Cool! So what brings you to Rust Belt Rust and the Rust language in general? **Pete:** I got interested in Rust - I’ve always sort of been interested in doing systems programming, but a little bit anxious about buffer overflows, and sort of the error-prone-ness of it - and when I learned about Rust, I thought, like, “Oh, maybe this has removed some of the things that were preventing me from diving in to systems programming, and so I’m trying to learn Rust now. **Chris:** Awesome. How long have you been at it with learning Rust? **Pete:** I actually just tracked this last night - I’ve spent 39 hours so far, reading the Rust book and doing exercises and so forth, and next week I’m headed to the Recur (?) Center to spend six weeks full time learning Rust. **Chris:** That’s awesome. I’m kind of a little jealous. That sounds really fun. Do you have any ideas of where in particular you might like to use it yet - things like that, or...? **Pete:** Um, I have some projects. I’d like to make a command line utility to help developers understand, like SSH keys, and cryptocertificates um, from, like, a dev ops side, and other than that, kind of, yeah, command line utilities and developer tools. **Chris:** That’s awesome. What has been best so far in learning Rust, and then maybe also worst? **Pete:** Um, I think, I’m not really sure I have a good answer to what things so far. I found the thing that was difficult for me is the format of the standard library documentation I find difficult to scan and read, so there’s like a lot of information on the screen that doesn’t seem well-differentiated, and it just seems like a wall of text and I’m a little bit disoriented. So, that has been a little bit of a struggle, but otherwise, I think the - I guess I would say - the best thing, I think, is the crates and cargo design, and I feel like the team that did that had a lot of good lessons learned from their predecessors, so I’m pretty psyched about that. **Chris:** Excellent. Thank you. Anything else that jumps out at you, here at Rust Belt Rust, or comments to the community, etcetera? **Pete:** I think the community is great; everyone’s been really friendly, um, and the conference has been, you know, the conference has been great, and I’ve been learning a lot, so I’m pretty excited about it. **Chris:** Awesome. Thanks for your time. **Pete:** Thank you! ================================================ FILE: landing/index.html ================================================ New Rustacean: A Podcast About Learning Rust

New Rustacean logo image

About

Hello! This is a podcast about learning the programming language Rust—from scratch! Apart from this spiffy landing page, all the site content is built with Rust's own documentation tools. You can hear more about why I'm doing this in e000: Why Am I Here? And there's much more to come!

  • Landing page design by Chris Krycho.
  • All content licensed under a Creative Commons Attribution license: do whatever you like with this; just credit me!
  • Rust documentation design belongs to the Rust language team, not me!
================================================ FILE: landing/landing.css ================================================ /** * Copyright 2013 The Rust Project Developers. See the COPYRIGHT * file at the top-level directory of this distribution and at * http://rust-lang.org/COPYRIGHT. * * Licensed under the Apache License, Version 2.0 or the MIT license * , at your * option. This file may not be copied, modified, or distributed * except according to those terms. */ @font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 400; src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff'); } @font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 500; src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff'); } @font-face { font-family: 'Source Serif Pro'; font-style: normal; font-weight: 400; src: local('Source Serif Pro'), url("SourceSerifPro-Regular.woff") format('woff'); } @font-face { font-family: 'Source Serif Pro'; font-style: italic; font-weight: 400; src: url("Heuristica-Italic.woff") format('woff'); } @font-face { font-family: 'Source Serif Pro'; font-style: normal; font-weight: 700; src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff'); } @font-face { font-family: 'Source Code Pro'; font-style: normal; font-weight: 400; src: local('Source Code Pro'), url("SourceCodePro-Regular.woff") format('woff'); } @font-face { font-family: 'Source Code Pro'; font-style: normal; font-weight: 600; src: local('Source Code Pro Semibold'), url("SourceCodePro-Semibold.woff") format('woff'); } @import "normalize.css"; /* Landing page styles */ html { font-family: 'Source Serif Pro'; font-weight: 400; background: repeating-linear-gradient( -45deg, RGBA(166, 174, 179, 1), RGBA(166, 174, 179, 1) 40px, RGBA(15, 23, 26, .67) 40px, RGBA(15, 23, 26, .67) 80px ); } body { height: 100%; width: 100%; margin: 0; padding: 0; } h1 { font-family: 'Fira Sans'; font-weight: normal; } main { padding: 2em 0; width: 100%; height: auto; max-height: 35%; } .card { margin: auto; max-width: 50vh; height: 50vh; position: relative; cursor: pointer; } .pad { padding: 1em; } .card_side { position: absolute; top: 0; left: 0; height: 100%; width: 100%; -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -ms-backface-visibility: hidden; backface-visibility: hidden; -webkit-transform-origin: left 50% -2em; -moz-transform-origin: left 50% -2em; -ms-transform-origin: left 50% -2em; transform-origin: left 50% -2em; transition: all 0.5s ease; box-shadow: 0 0 8px RGBA(15, 23, 26, 1); } .front { background: RGBA(253, 251, 250, 1); } .back { background: RGBA(87, 66, 43, 1); color: RGBA(253, 251, 250, 1); transform: rotateY(180deg); } .back a { color: RGBA(166, 174, 179, 1); } .flipped.card .front { -webkit-transform: rotateY(-180deg); -moz-transform: rotateY(-180deg); -ms-transform: rotateY(-180deg); transform: rotateY(-180deg); } .flipped.card .back { -webkit-transform: rotateY(0); -moz-transform: rotateY(0); -ms-transform: rotateY(0); transform: rotateY(0); } .flipped .card_side { -webkit-transform-origin: right 50% -2em; -moz-transform-origin: right 50% -2em; -ms-transform-origin: right 50% -2em; transform-origin: right 50% -2em; } .card:hover .front { -webkit-transform: rotateY(-10deg); -moz-transform: rotateY(-10deg); -ms-transform: rotateY(-10deg); transform: rotateY(-10deg); box-shadow: 8px 0 20px RGBA(15, 23, 26, 1); } .card:hover .back { -webkit-transform: rotateY(170deg); -moz-transform: rotateY(170deg); -ms-transform: rotateY(170deg); transform: rotateY(170deg); box-shadow: -8px 0 20px RGBA(15, 23, 26, 1); } .flipped.card:hover .front { -webkit-transform: rotateY(-170deg); -moz-transform: rotateY(-170deg); -ms-transform: rotateY(-170deg); transform: rotateY(-170deg); } .flipped.card:hover .back { -webkit-transform: rotateY(10deg); -moz-transform: rotateY(10deg); -ms-transform: rotateY(10deg); transform: rotateY(10deg); } .card_side img { width: 100%; height: auto; } /* ----- Common styles ----- */ .plain_list { list-style: none; padding: 0; margin: 0; } /* ----- Navigation styles ----- */ nav { background: RGBA(166, 142, 116, 1); border-top: 2px solid RGBA(87, 66, 43, 1); font-family: 'Fira Sans'; } nav li { border-bottom: 2px solid RGBA(87, 66, 43, 1); } nav li a { display: block; height: 2em; line-height: 2; padding: 0.5em 0; width: 100%; text-align: center; color: inherit; text-decoration: none; transition: all 0.5s ease; } nav li a:hover { background: RGBA(87, 66, 43, 1); color: RGBA(253, 251, 250, 1); } nav li a:active { background: RGBA(240, 80, 34, 1); transition: all 0.1s ease-out; } .fa { padding-right: 0.25em; } /* Special styles for navigation */ nav .inner_list { padding: 0 10%; display: flex; flex-direction: row; justify-content: center; text-align: center; border-bottom: RGBA(87, 66, 43, 1); } nav .inner_list li { flex: 1 0 20%; border: none; } .funding .fa { font-size: 80%; } @media screen and (max-width: 580px) { nav .inner_list { display: block; padding: 0; border-bottom: none; } nav .inner_list li { width: 100%; border-bottom: 2px solid RGBA(87, 66, 43, 1); } nav .inner_list li:last-of-type { border-bottom: none; } } /* ----- Footer styles ----- */ footer { background: RGBA(240, 80, 34, 1); color: RGBA(253, 251, 250, 1); padding: 2em 0; margin: 0; text-align: center; border-bottom: 2px solid RGBA(87, 66, 43, 1); } footer a { color: RGBA(253, 251, 250, 1); font-family: 'Source Code Pro'; transition: all 0.5s ease; } footer a:hover { color: RGBA(15, 23, 26, 1); } .colophon_list li { line-height: 1.2; padding-bottom: 1em; } /* ----- Page styles ----- */ .page-content { width: 100%; background: white; margin: auto; padding-top: 1em; padding-bottom: 1em; } .page-content > * { max-width: 40em; text-align: center; margin-left: auto; margin-right: auto; } /* ----- Component styles ----- */ .sponsors-list { padding-left: 0; list-style-type: none; text-align: center; } .sponsors-list__sponsor { padding: 0 0 1em; font-size: 1.5em; } .sponsors-list__sponsor-link { color: RGBA(240, 80, 34, 1); } .sponsors-list__sponsor-name { display: inline-block; width: 100%; } .sponsors-list__sponsor-name::before, .sponsors-list__sponsor-name::after { content: '✨'; padding: 0 0.5em; } .sponsors-list__sponsor-dates { font-style: italic; display: inline-block; width: 100%; } ================================================ FILE: landing/sponsors.html ================================================ New Rustacean: A Podcast About Learning Rust

Sponsors

Sponsors who have contributed at least $25 to the show in any given month are listed here, along with the months of their sponsorship at that level. These sponsors are a huge part of what makes the show sustainable for me, and have my heartfelt thanks.

  • Landing page design by Chris Krycho.
  • All content licensed under a Creative Commons Attribution license: do whatever you like with this; just credit me!
  • Rust documentation design belongs to the Rust language team, not me!
================================================ FILE: resources/.nojekyll ================================================ ================================================ FILE: resources/CNAME ================================================ newrustacean.com ================================================ FILE: resources/feed.xml ================================================ New Rustacean https://newrustacean.com A show about the Rust programming language and the people who use it. Feeder 3 3.6.7(3212); Mac OS X Version 10.14.4 (Build 18E226) http://reinventedsoftware.com/feeder/ http://blogs.law.harvard.edu/tech/rss en 2015–2019 Chris Krycho hello@newrustacean.com (Chris Krycho) hello@newrustacean.com (Chris Krycho) Mon, 27 May 2019 09:14:50 -0600 Mon, 27 May 2019 09:14:50 -0600 https://newrustacean.com/podcast.png New Rustacean https://newrustacean.com 144 144 A show about the Rust programming language and the people who use it. Chris Krycho A show about the Rust programming language and the people who use it. Deep dive teaching episodes, news updates, and interviews with people around the Rust community. Rust,programming,programming languages,software clean Chris Krycho hello@newrustacean.com no episodic Meta 3: Happy Coding https://newrustacean.com/show_notes/meta/_3/ A story and a dream (and the promise of Rust): the final episode of New Rustacean!

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Contact

]]>
Mon, 27 May 2019 09:15:00 -0600 769CEFA3-B4B9-4B5C-B9BA-62587F2F98B3 A story and a dream (and the promise of Rust): the final episode of New Rustacean! A story and a dream (and the promise of Rust): the final episode of New Rustacean! 16:35 full
News: Rust 1.35 https://newrustacean.com/show_notes/news/rust_1_35/ WASI, Option::copied, and the future of async/await syntax!

Show Notes

Sponsors

Thanks to Parity for sponsoring the show and hiring Rust developers!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Thu, 23 May 2019 21:00:00 -0600 04470049-93B0-4B8B-9574-0B72F4AC37CD WASI, `Option::copied`, and the future of async/await syntax! WASI, `Option::copied`, and the future of async/await syntax! 18:18 full
CYSK: bindgen and cbindgen https://newrustacean.com/show_notes/cysk/bindgen_cbindgen/ Automatic generation of FFI types between Rust and C APIs.

Show Notes

Sponsors

Thanks to Parity for sponsoring the show and hiring Rust developers!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Fri, 17 May 2019 20:10:00 -0600 35135E76-3E12-437E-AA90-38AB3BC51CD2 Automatic generation of FFI types between Rust and C APIs. Automatic generation of FFI types between Rust and C APIs. 18:10 full
e031: FFI Deep Dive http://Exposing%20Rust%20types%20and%20functions%20to%20C%20API%20consumers. Exposing Rust types and functions to C API consumers.

Show Notes

It’s impossible to make the declarations below follow the order I talked through them on the recording without also making them horrible to read, so just use this outline instead:

  1. add_in_rust
  2. Strings
    1. concat_strings
    2. free_rust_string
  3. Point
    1. point_translate
  4. union
  5. OpaquePoint
    1. opaque_point_new
    2. opaque_point_translate
    3. opaque_point_free

Sponsors

Thanks to Parity for sponsoring the show and hiring Rust developers!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 13 May 2019 20:40:00 -0600 976CD791-23E6-44D5-86EC-D7C28A6E8D68 Exposing Rust types and functions to C API consumers. 25:18 full
e030: Can You See Me Now? https://newrustacean.com/show_notes/e030/ Item visibility and pub(<restricted>) as API design tools.

Show Notes

The easiest and most effective way to understand the example in this case will simply be to look directly at the source code. You can read the docs for each of the nested modules, but you’ll be doing a lot of navigating around for that.

Also, I am using Cargo’s --document-private-items flag, so that you can see all the items in all the modules, even those which are not public, but note that usually you would not see docs for those!

Sponsors

Thanks to Manning for sponsoring the show and giving all of you a 40%-off discount on their whole store (but especially their WebAssembly in Action MEAP) at deals.manning.com/new-rustacean!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Fri, 26 Apr 2019 22:00:00 -0600 EC1C6E98-88CD-46A4-881B-F7F0B998F986 Item visibility and `pub(<restricted>)` as API design tools. Item visibility and `pub(<restricted>)` as API design tools. 18:37 full
News: Rust 1.33 and 1.34 https://newrustacean.com/show_notes/news/rust_1_33_1_34/ Moar const fn, some Pin, and alternative Cargo registries!

Show Notes

Sponsors

Thanks to Parity for sponsoring the show and hiring Rust developers!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 20 Apr 2019 13:15:00 -0600 1C81D2C3-3FDE-40BE-B045-B549D84FDDD4 Moar `const fn`, some `Pin`, and alternative Cargo registries! Moar `const fn`, some `Pin`, and alternative Cargo registries! 18:58 full
e029: I’m Out to C https://newrustacean.com/show_notes/e029/ Using Rust’s Foreign Function Interface (FFI) with C!

Show Notes

The code samples here directly match the things I described in the show, so you will likely want to look at add and ffi::add, then Point, translate, and ffi::translate in that order.

Other helpful Rust FFI discussions:

Sponsors

Thanks to Manning for sponsoring the show and giving all of you a 40%-off discount on their whole store (but especially Carol Nichols’ and Jake Goulding’s Rust in Motion video content and the Rust in Action MEAP!) at deals.manning.com/new-rustacean

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Wed, 03 Apr 2019 22:15:12 -0600 7A179962-9568-40BF-97D8-9C722ABB9ECF Using Rust’s Foreign Function Interface (FFI) with C! Using Rust’s Foreign Function Interface (FFI) with C! 23:20 full
Bonus 14: How the Sausage Gets Made https://newrustacean.com/show_notes/bonus/_14/ How I make the show, and why you won’t find it on Google Play, Spotify, or Stitcher.

Show Notes

Sponsors

Thanks to Parity for sponsoring the show and hiring Rust developers!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 23 Mar 2019 20:50:12 -0600 EB5C1DD3-07B5-42CC-B821-ACC8A10045D9 How I make the show, and why you won’t find it on Google Play, Spotify, or Stitcher. How I make the show, and why you won’t find it on Google Play, Spotify, or Stitcher. 19:22 full
Bonus 13: I Still Make Silly Mistakes https://newrustacean.com/show_notes/bonus/_13/ A story about parsing command-line arguments manually and some thoughts on “rookie mistakes.”

Show Notes

Sponsors

Thanks to Parity for sponsoring the show and hiring Rust developers!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Thu, 28 Feb 2019 07:20:00 -0700 09C99DA4-0275-4128-BE30-26442421BE86 A story about parsing command-line arguments manually and some thoughts on “rookie mistakes.” A story about parsing command-line arguments manually and some thoughts on “rookie mistakes.” 12:13 full
e028: Meet My Associates https://newrustacean.com/show_notes/e028/ Associated items: functions and methods, constants, types, and (very briefly!) GATs.

Show Notes

Sponsors

Thanks to Manning for sponsoring the show and giving all of you a 40%-off discount on their whole store (but especially Carol Nichols’ and Jake Goulding’s Rust in Motion video content and the Rust in Action MEAP!) at deals.manning.com/new-rustacean

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Thu, 21 Feb 2019 21:30:00 -0700 69BCF3A2-39EE-478C-A385-3C88DA9CDC68 Associated items: functions and methods, constants, types, and (very briefly!) GATs. Associated items: functions and methods, constants, types, and (very briefly!) GATs. 23:07 full
News: Rust 1.32 https://newrustacean.com/show_notes/news/rust_1_32/ dbg!, unified paths, more places you can use Self, and a bunch of const fn stabilizations—plus some neat community highlights!

Show Notes

Sponsors

Thanks to Parity for sponsoring the show again. Go check out their Rust jobs!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Tue, 22 Jan 2019 20:20:57 -0700 4C56D97A-DB60-4770-8C11-047C81BEE293 `dbg!`, unified paths, more places you can use `Self`, and a *bunch* of `const fn` stabilizations—plus some neat community highlights! `dbg!`, unified paths, more places you can use `Self`, and a *bunch* of `const fn` stabilizations—plus some neat community highlights! 18:03 full
News: Rust 1.31 and the 2018 Edition, Part II https://newrustacean.com/show_notes/news/rust_1_31/part_2/ Stabilizing rustfmt, clippy, tool lints, and const fn (all in both editions!), and the 2018 Edition-specific features: syntax changes and non-lexical lifetimes!

Show Notes

Sponsors

Thanks to Parity for sponsoring the show again. Go check out their Rust jobs!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 14 Jan 2019 15:01:39 -0700 C21A0F06-75C6-45AD-9081-4D6DE378EA7E Stabilizing rustfmt, clippy, tool lints, and `const fn` (all in both editions!), and the 2018 Edition-specific features: syntax changes and non-lexical lifetimes! Stabilizing rustfmt, clippy, tool lints, and `const fn` (all in both editions!), and the 2018 Edition-specific features: syntax changes and non-lexical lifetimes! 22:42 full
News: Rust 1.31 and the 2018 Edition, Part I https://newrustacean.com/show_notes/news/rust_1_31/part_1/ An overview of the edition, and some of the improvements that are available in both the 2015 and 2018 editions: better lifetime elision, some Cargo features, and some library stabilizations.

Show Notes

Sponsors

Thanks to Parity for sponsoring the show again. Go check out their Rust jobs!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 07 Jan 2019 08:00:00 -0700 108A2246-BF83-46DC-8757-D034324F5D2B An overview of the edition, and some of the improvements that are available in both the 2015 and 2018 editions: better lifetime elision, some Cargo features, and some library stabilizations. An overview of the edition, and some of the improvements that are available in both the 2015 and 2018 editions: better lifetime elision, some Cargo features, and some library stabilizations. 20:54 full
Interview: Integer32 https://newrustacean.com/show_notes/interview/integer32/ Show Notes

Things we mentioned on the show:

Sponsors

Thanks to Manning for sponsoring this episode; don’t forget to grab some of their content at 40% off using the code podnewrust18!

Thanks to Parity for sponsoring the show again. Go check out their Rust jobs!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 31 Dec 2018 16:00:00 -0700 7645717E-336D-4F21-9B7B-C29167BC0D70 Carol Nichols || Goulding and Jake Goulding Talking with Carol and Jake about _The Rust Programming Language_, _Rust in Motion_, and Rust Belt Rust. With a bonus discussion about the value of focusing on our kids over just building big businesses. 41:01 full
e027: Trust Me; I Promise! https://newrustacean.com/show_notes/e027/ An intro to unsafe Rust and Rust’s idea of safety.

Show Notes

Errata

A quick correction: on the show I said that a trait needed to be unsafe when it had an unsafe fn method. This isn’t correct: safe traits can have unsafe methods, and unsafe traits can exist without any methods at all (as implied by my reference to Send and Sync). You can see this in practice in the following example, which compiles just fine!

trait ASafeTrait {
    unsafe fn unsafe_method() {}
}

unsafe AnUnsafeTrait {}

The idea of an unsafe trait is that it has some conditions which you must uphold to safely implement it – again, just as with Send and Sync. In the case of most traits, this will be because some trait method has invariants it needs to hold else it would cause undefined behavior. For another example of this, see the (unstable as of the time of recording) trait std::iter::TrustedLen.

Thanks to Rust language team member @centril for noting this to me after listening when I was recording the show live!

Examples

Borrow-checked code in unsafe

let mut f = String::from("foo");

unsafe {
    let borrowed = &mut f;
    let borrow_again = &f;

    println!("{}", borrowed);

    // This would be unsafe and throw an error:
    // println!("{}", borrow_again);
}

(See it in a playground)

Safely mutating a raw pointer
let f = Box::new(12);
let mut g = Box::into_raw(f);
g = &mut (g + 10);

(See it in a playground)

Sponsors

Thanks to Parity for sponsoring the show again. Go check out their Rust jobs!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Fri, 30 Nov 2018 21:46:59 -0700 F05FA5EA-F0E5-43A1-A05A-71061CAC6F1D An intro to `unsafe` Rust and Rust's idea of safety. An intro to `unsafe` Rust and Rust's idea of safety. 21:27 full
News: Rust 1.29 and 1.30 https://newrustacean.com/show_notes/news/rust_1_29_1_30/ Procedural macros, better paths, and the Rust 2018 beta!

Show Notes

Rust 1.29:

Rust 1.30:

Sponsors

Thanks to Parity for sponsoring the show again. Go check out their Rust jobs!

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Fri, 16 Nov 2018 07:10:41 -0700 FA4DE9FA-543A-4B55-8229-1C9E8E6867BD Procedural macros, better paths, and the Rust 2018 beta! Procedural macros, better paths, and the Rust 2018 beta! 17:33 full
Bonus 12: Translating Between Languages https://newrustacean.com/show_notes/bonus/translating_between_languages/ Musings inspired by a project translating TypeScript to Rust

Sponsors

Thanks to Manning for sponsoring the show and giving all of you a 40%-off discount on their whole store (but especially Carol Nichols’ and Jake Goulding’s Rust in Motion video content and the Rust in Action MEAP!) at deals.manning.com/new-rustacean

Patreon Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

#[doc(include = “../docs/bonus/translating-between-languages.md”)] pub struct Script;

]]>
Tue, 23 Oct 2018 21:30:00 -0600 2B852FBD-75E5-4A1B-BB33-6934C48DE606 Musings inspired by a project translating TypeScript to Rust 15:43 full
Bonus 11: Burnout https://newrustacean.com/show_notes/bonus/burnout/ What burnout is, the many ways it can happen to us, and what we can do about it.

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 22 Sep 2018 21:21:51 -0600 AA893E9C-9C9F-4C3C-9EAE-C094B36006DD What burnout is, the many ways it can happen to us, and what we can do about it. 27:11 full
News: Rust 1.28 https://newrustacean.com/show_notes/news/rust_1_28/ Stable `#[global_allocator]`, more Rust 2018 Edition schedule news, video learning resources, and a static site generator!

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Thu, 16 Aug 2018 17:00:00 -0600 E520BED3-72F2-48A0-A4A6-CEC066A465B1 Stable `#[global_allocator]`, more Rust 2018 Edition schedule news, video learning resources, and a static site genrator! full
e026: Functional Programming Ideas https://newrustacean.com/show_notes/e026/ How Rust both borrows from FP languages and charts its own, very different course.

Show Notes

Sponsored by Parity Technologies! Parity is hiring Rust developers so if you’re interested, you should check out their job listings!

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Tue, 24 Jul 2018 20:02:06 -0600 E18F17D8-EFC5-4C9F-B056-D0F86AA3D540 How Rust both borrows from FP languages and charts its own, very different course. How Rust both borrows from FP languages and charts its own, very different course. 18:33 full
e025: Traits Deep Dive, Part III https://newrustacean.com/show_notes/e025/ Closure traits, `impl trait`, `dyn trait`, and object safety!

Show Notes

Sponsored by Parity Technologies! Parity is hiring Rust developers so if you’re interested, you should check out their job listings!

Example

You can see all of the pieces of the final example described in the show here (and the module has the required definitions for Point).

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Wed, 04 Jul 2018 19:27:56 -0600 7D91156A-9084-4737-A872-E50FCF7ED72A Closure traits, `impl trait`, `dyn trait`, and object safety! Closure traits, `impl trait`, `dyn trait`, and object safety! 20:36 full
News: Rust 1.27 https://newrustacean.com/show_notes/news/rust_1_27/ Stable SIMD, `dyn trait`, `rustfix` and the alpha release of the Rust 2018 Edition Preview!

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 30 Jun 2018 13:57:28 -0600 2A20BDFE-C68B-4655-905C-EAF5F79D31CE Stable SIMD, `dyn trait`, `rustfix` and the alpha release of the Rust 2018 Edition Preview! Stable SIMD, `dyn trait`, `rustfix` and the alpha release of the Rust 2018 Edition Preview! 15:49 full
e024: Traits Deep Dive, Part II https://newrustacean.com/show_notes/e024/ Operators as sugar for traits, traits as generic constraints, monomorphization, and universal and existential types.

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Tue, 19 Jun 2018 20:01:50 -0600 AF24982B-5018-4731-9DA4-FE6DF3902822 Operators as sugar for traits, traits as generic constraints, monomorphization, and universal and existential types. Operators as sugar for traits, traits as generic constraints, monomorphization, and universal and existential types. 20:33 full
CYSK: The wasm tools https://newrustacean.com/show_notes/cysk/wasm/ wasm intro, wasm-bindgen, and wasm-pack

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Thu, 31 May 2018 21:53:47 -0600 96AE12E7-AC4D-40F6-89A7-BE01791C5163 wasm intro, `wasm-bindgen`, and `wasm-pack` wasm intro, `wasm-bindgen`, and `wasm-pack` 15:46 full
News: Rust 1.26 https://newrustacean.com/show_notes/news/rust_1_26/ impl trait, match on references, Results from main, and more. A good way to mark three years since Rust 1.0!

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 14 May 2018 20:45:00 -0600 25BF49BF-C267-4BFA-B36F-D186D0074396 `impl trait`, `match` on references, `Result`s from `main`, and more. A good way to mark three years since Rust 1.0! 17:27 full
e023: Traits Deep Dive, Part I https://newrustacean.com/show_notes/e023/ Defining and using your own traits, using other crates' traits, and the orphan rule.

Show Notes

Traits—

Also of interest: specialization:

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 28 Apr 2018 15:33:44 -0600 8F524C0B-AC10-4997-95D8-F55EC1398544 Defining and using your own traits, using other crates' traits, and the orphan rule. Defining and using your own traits, using other crates' traits, and the orphan rule. 20:33 full
News: Rust 1.25 https://newrustacean.com/show_notes/news/rust_1_25/ Paths and matches and SIMD, cargo new changes, and tons of community-driven learning materials!

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 31 Mar 2018 14:34:45 -0600 8A342F53-509F-48D3-92F2-101FA919FA05 Paths and matches and SIMD, cargo new changes, and tons of community-driven learning materials! 14:12 full
Bonus 10: “Becoming a Contributor” https://newrustacean.com/show_notes/bonus/_10/ My Rust Belt Rust 2017 talk!

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 17 Mar 2018 13:15:23 -0600 8E8D5D5C-620C-4EEE-982B-093DB6845335 My Rust Belt Rust 2017 talk! 31:02 full
News: Rust 1.24 https://newrustacean.com/show_notes/news/rust_1_24/ Performance wins, incremental compilation, and the Rust 2018 Roadmap and Epoch.

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Thu, 01 Mar 2018 20:37:32 -0700 93D8888B-8802-4567-8821-84AE9246F1D9 Performance wins, incremental compilation, and the Rust 2018 Roadmap and Epoch. 18:28 full
CYSK: Serde https://newrustacean.com/show_notes/cysk/serde/ The library for serialization and deserialization in Rust.

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 10 Feb 2018 15:24:26 -0700 623E9CBB-7B28-4E61-8C4F-8756204414CF The library for serialization and deserialization in Rust. The library for serialization and deserialization in Rust. 12:29 full
e023: Send and Sync https://newrustacean.com/show_notes/e022/ The “marker traits” that Rust uses for safe concurrency.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Wed, 31 Jan 2018 20:45:00 -0700 8F9D3A8C-9236-4FCD-ADAB-5AACEA0EAA8E The “marker traits” that Rust uses for safe concurrency. The “marker traits” that Rust uses for safe concurrency. 20:36 full
Interview – Diesel 1.0, with Sean Griffin – Part 2 https://newrustacean.com/show_notes/interview/diesel_1_0/part_2/ Getting Diesel to 1.0, writing docs and exposing problems with the API, improving Diesel in the future, and thinking about API design for open source libraries in general.

Show notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sun, 21 Jan 2018 16:25:23 -0700 EF73A61F-960D-4857-9492-E5FFB2D019AB Getting Diesel to 1.0, writing docs and exposing problems with the API, improving Diesel in the future, and thinking about API design for open source libraries in general. Getting Diesel to 1.0, writing docs and exposing problems with the API, improving Diesel in the future, and thinking about API design for open source libraries in general. 31:01 full
Interview – Diesel 1.0, with Sean Griffin – Part 1 https://newrustacean.com/show_notes/interview/diesel_1_0/part_1/ Growing Diesel's community, self-imposed technical challenges, and some of the ways Diesel has contributed to the Rust ecosystem.

Show notes

Sponsors

Become a sponsor

Contact

]]>
Sat, 13 Jan 2018 12:50:00 -0700 CC652BFB-A049-45F8-8961-C424DEBBA6E7 Growing Diesel's community, self-imposed technical challenges, and some of the ways Diesel has contributed to the Rust ecosystem. Growing Diesel's community, self-imposed technical challenges, and some of the ways Diesel has contributed to the Rust ecosystem. 31:57 full
News: Rust 1.23 https://newrustacean.com/show_notes/news/rust_1_23/ Show notes

Sponsors

Become a sponsor

Contact

]]>
Fri, 05 Jan 2018 21:30:00 -0700 48869401-8C9E-4FF8-8904-D3B969C40FCB Rustdoc changes, the first `impl` period, Firefox Quantum, and more wasm! Rustdoc changes, the first `impl` period, Firefox Quantum, and more wasm! 16:54 full
Increasing Rust's Reach: Matt Gathu https://newrustacean.com/show_notes/interview/irr_2017/matt_gathu/ Matt’s experience porting wget to Rust.

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 30 Dec 2017 16:00:00 -0700 9C7DCF08-7108-41F4-9248-3A7BE4224605 Matt's experience porting wget to Rust. Matt's experience porting wget to Rust. 21:13 full
Increasing Rust's Reach: Lee Baillie Lee’s experience designing a new website for Rust.

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Tue, 26 Dec 2017 13:35:16 -0700 F7C7DD57-3879-4F0B-84B7-FB048BD27316 Lee’s experience designing a new website for Rust. Lee’s experience designing a new website for Rust. 24:06 full
Increasing Rust's Reach: Anna Liao https://newrustacean.com/show_notes/interview/irr_2017/anna_liao/ Anna's experience learning Rust while porting a Raspberry Pi Python project as part of the Increasing Rust’s Reach 2017 program.

Show Notes

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Wed, 20 Dec 2017 22:00:00 -0700 D9A7E541-7150-42D4-9C7F-4D888738B29E Chris Krycho Anna's experience learning Rust while porting a Raspberry Pi Python project as part of the Increasing Rust’s Reach 2017 program. 29:28 full
RBR 2017: Katie Nolan https://newrustacean.com/show_notes/interview/rbr_2017/katie_nolan/ Fri, 15 Dec 2017 07:46:41 -0700 13D7F9E3-5FF9-46DF-854B-EC6C0071E0C2 Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 5:21 full RBR 2017: Ben Beckwith https://newrustacean.com/show_notes/interview/rbr_2017/ben_beckwith/ Thu, 14 Dec 2017 18:26:20 -0700 DB1645B8-3609-4D0A-9799-5FA13093C42F Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 5:42 full RBR 2017: Andrew Hobden https://newrustacean.com/show_notes/interview/rbr_2017/andrew_hobden/ Wed, 13 Dec 2017 16:20:00 -0700 38546A70-AF33-4779-8C51-460BBB9639DC Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 6:00 full RBR 2017: Parry Wilcox https://newrustacean.com/show_notes/interview/rbr_2017/parry_wilcox/ Tue, 12 Dec 2017 07:05:27 -0700 22BFBE09-3535-47CC-9B24-E42F23E939CF Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 6:30 full RBR 2017: Matthias Endler https://newrustacean.com/show_notes/interview/rbr_2017/matthias_endler/ Mon, 11 Dec 2017 17:50:53 -0700 F5350AC4-F5F5-4264-912C-79F4E6FF9365 Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 6:30 full RBR 2017: Ben Striegel https://newrustacean.com/show_notes/interview/rbr_2017/ben_striegel/ Sun, 10 Dec 2017 08:15:05 -0700 EF790105-EDD7-4E65-BC67-05354771915D Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 6:10 full RBR 2017: Holden Marcsisin https://newrustacean.com/show_notes/interview/rbr_2017/holden_marcsisin/ Sat, 09 Dec 2017 09:15:00 -0700 954E2D5F-0982-4148-B8C3-BFEBA198594B Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 7:07 full RBR 2017: Esty Thomas https://newrustacean.com/show_notes/interview/rbr_2017/esty_thomas/ Thu, 07 Dec 2017 19:15:00 -0700 A663E935-6F40-4085-9B45-8B9D2EF0C585 Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 6:04 full RBR 2017: Thomas Gideon https://newrustacean.com/show_notes/interview/rbr_2017/thomas_gideon/ Wed, 06 Dec 2017 16:30:00 -0700 539362B6-B68B-428E-A3BE-493B0EBFC784 Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 5:35 full RBR 2017: Tom Kriezkowski https://newrustacean.com/show_notes/interview/rbr_2017/tom_kriezkowski/ A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28.

]]>
Sun, 26 Nov 2017 16:14:25 -0700 C59826B3-E6E7-47EE-8077-B14A49FA23DA Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 5:00 full
News: Rust 1.21 and 1.22 https://newrustacean.com/show_notes/news/rust_1_21_1_22/ Quality of life improvements, Failure, wasm, and rustdoc fun.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Fri, 24 Nov 2017 13:47:24 -0700 CCCABE57-4293-427B-A655-0368884A23EC Quality of life improvements, <code>Failure</code>, wasm, and rustdoc fun. 15:53 full
RBR 2017: Jess Saxeter https://newrustacean.com/show_notes/interview/rbr_2017/jess_saxeter/ Sun, 19 Nov 2017 13:00:00 -0700 E2E9A3A8-7B9F-4379-82DD-B021EC9F5A28 A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 5:17 full RBR 2017: Pete Lyons https://newrustacean.com/show_notes/interview/rbr_2017/pete_lyons/ A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28.

]]>
Sat, 18 Nov 2017 13:55:02 -0700 E0CDEC86-D180-4AB3-968E-6DB4718D5CA7 Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 4:54 full
RBR 2017: Arun Kulsheshthra https://newrustacean.com/show_notes/interview/rbr_2017/arun_kulshreshthra/ Tue, 14 Nov 2017 20:02:51 -0700 3BCC7FC9-B335-45A3-BE58-1B2DE224958B Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 5:27 full RBR 2017: Anthony Deschamps https://newrustacean.com/show_notes/interview/rbr_2017/anthony_deschamps/ A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28.

## Transcript

**Chris:** hello! Can you tell me your name and a little bit about yourself?

**Anthony:** My name is Anthony Deschamps, I, um, I’m a software developer, I work in Automotive.

**Chris:** Oh! Very interesting. Long-time listeners will recognize Anthony’s name as a sponsor of the show; thank you for sponsoring the show!

**Anthony:** You’re welcome!

**Chris:** So, what got you into Rust?

**Anthony:** I’ve talked about this earlier; I actually can’t remember how I first came across it. Um, I remember my friends being excited about it and looking at it at some point, um, but what really hooked me is that I have a huge amount of respect for C+ +, uh, it was one of my first languages, and to me, Rust feels like C+ + with decades of learned lessons. If we have a clean slate, and what you can do with a fresh start.

**Chris:** Yeah. How long - do you remember roughly, obviously you don’t remember exactly when, but - do you remember roughly how long...pre 1.0, post 1.0?

**Anthony:** Uh, probably about a year ago, so, somewhere after 1.10 or roundabouts.

**Chris:** Okay. Very good. What has your experience of learning Rust been like? Good, bad, ugly?

**Anthony:** Um, it’s made my C+ + better.

**Chris:** Yeah.

**Anthony:** Everything thing that I struggled with in Rust was really just a lesson for what I could be doing better in other places.

**Chris:** What are you using Rust for presently? Are you able to use it at work at all, or is it side projects entirely, still?

**Anthony:** So, a combination of hobby projects, uh, when I have time. And, a little bit at work. It’s one of those things where it is a little bit of a risk, a newer thing, so it’s been nice to try it out on some small things, see how it goes, and realize that I do like it and get excited about hoping to use it more.

**Chris:** Yeah. What kind of side projects have you been able to do?

**Anthony:** Um, when I get around to strapping a Raspberry Pi to a balloon and sending it up to the stratosphere to take some photos, that’ll be in Rust.

**Chris:** That’s awesome.

**Anthony:** I also like to play around with arduinos, and LEDs are fun, and I’m using a little bit of Rust there.

**Chris:** Cool. Is there anything in particular that’s caught your attention either with this conference or with the Rust community in general?

**Anthony:** The most exciting thing to me is meeting the people who are making the things that I enjoy using. Uh, it seems obvious when you really think about it, but, um, the things that you use are not made by some...cloud, or void, or they don’t just come out of nowhere, they’re made from real people, who really enjoy working on what they’re doing, and are really excited to talk to you about it.

**Chris:** I share that sentiment deeply. Thank you for your time!

**Anthony:** Well, thank you so much for the podcast. I really enjoy it.

**Chris:** My pleasure, and absolutely awesome, speaking of meeting people in person, it’s great to meet you in person!

**Anthony:** I agree. Thank you so much.

**Chris:** Thank you!

]]>
Mon, 13 Nov 2017 21:02:36 -0700 308765C1-9026-4AF4-9C34-36A337DC0BA3 A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 5:27 full
RBR 2017: Colin Dean https://newrustacean.com/show_notes/interview/rbr_2017/colin_dean/ Sat, 11 Nov 2017 13:22:48 -0700 6FD0CDF5-183D-4D03-A686-C7F4646DBE5C Chris Krycho A micro-interview recorded at Rust Belt Rust 2017, in Columbus, Ohio, October 27–28. 7:16 full Meta 2: Two milestones https://newrustacean.com/show_notes/meta/_2/ Two years and fifty episodes of New Rustacean—time to celebrate with stickers and shirts!

Shirts

Get them here! – available till Oct 9, 2017 at 8:00 PM EDT.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 25 Sep 2017 07:20:35 -0600 930E60FE-6493-4E5A-B373-2091DABAF8CC Chris Krycho 12:02 full
CYSK: Rayon https://newrustacean.com/show_notes/cysk/rayon/ Safe, threaded, parallel code in Rust!

Rayon

Other things referenced on the show

https://www.newrustacean.com/show_notes/e016/index.html ["embarassingly parallel"]: https://en.wikipedia.org/wiki/Embarrassingly_parallel

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 16 Sep 2017 12:25:00 -0600 2DC73B1F-BAC9-4466-8C50-3D65F2A43DFE Chris Krycho Safe, threaded, parallel code in Rust! 14:11 full
News: Rust 1.20 https://newrustacean.com/show_notes/news/rust_1_20/ Associated constants, conference season, meetups, and more!

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Thu, 31 Aug 2017 20:30:00 -0600 C3F7B727-EAE8-40AB-95B0-6D5F5A308921 Chris Krycho Associated constants, conference season, meetups, and more! 13:15 full
Bonus 9: Open source is mostly just normal people https://newrustacean.com/show_notes/bonus/_9/ My experience with ember-cli-typescript as an example: we're all just people muddling along and doing our best.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 14 Aug 2017 07:00:00 -0600 CC87FE1E-0E80-4B8F-B022-892E25C3E260 Chris Krycho My experience with ember-cli-typescript as an example: we're all just people muddling along and doing our best. full
e021: Keeping your types under cover https://newrustacean.com/show_notes/e021/ Using type aliases and creating custom type wrappers for more expressive and safer code.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 17 Jul 2017 18:35:00 -0600 963488ED-45D6-41FD-A47D-0A9798A7DF65 Chris Krycho Using type aliases and creating custom type wrappers for more expressive and safer code. 17:28 full
News 3: Increasing Rust's Reach https://newrustacean.com/show_notes/news/_3/ Growing Rust's diversity to help Rust grow.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Tue, 04 Jul 2017 14:00:00 -0600 EA9A1109-0E35-42ED-8B96-C91BCD123502 Chris Krycho Growing Rust's diversity to help Rust grow. 13:02 full
CYSK: Rocket https://newrustacean.com/show_notes/cysk/rocket/ An accessible, well-designed web framework in Rust!

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Fri, 30 Jun 2017 20:00:00 -0600 12EDC178-7E71-463E-9331-91462826BB0C Chris Krycho An accessible, well-designed web framework in Rust! 17:32 full
Interview 4 – Jonathan Turner: Part 3 https://newrustacean.com/show_notes/interview/_4/part_3/ Smoothing the Rust dev story

Future work on the RLS, in Rust itself, and in Servo.

Show Notes

Building the Rust Language Service:

Working on Servo:

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 17 Jun 2017 13:47:30 -0600 4676FF77-2A28-4F02-BE7F-6586774C42BA Chris Krycho Smoothing the Rust dev story: future work on the RLS, in Rust itself, and in Servo. 22:05 full
Interview 4 – Jonathan Turner: Part 2 https://newrustacean.com/show_notes/interview/_4/part_2/ Making Rust Better

Rust as the fusion of systems and high-level programming languages, and the RLS.

Show Notes

Building the Rust Language Service:

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Tue, 30 May 2017 14:36:28 -0600 E78DADCB-274E-4CCA-8876-2C467190F003 Making Rust Better: Rust as the fusion of systems and high-level programming languages, and the RLS. 25:09 full
Interview 4 – Jonathan Turner: Part 1 https://newrustacean.com/show_notes/interview/_4/part_1/ Getting to Rust

Background, TypeScript, coming to Rust, and how helpful the Rust community can be.

Show Notes

On Jonathan's programming backstory:

After the transition to working on Rust full-time:

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sun, 30 Apr 2017 20:13:06 -0600 D287B357-E8CB-402A-A19B-767E819BEA14 Chris Krycho Background, TypeScript, coming to Rust, and how helpful the Rust community can be. 22:50 full
CYSK: RLS https://newrustacean.com/show_notes/cysk/_3/ Where the RLS came from, what it can do, and how you can start using it today!

Notes

One major ergonomic improvement to developing in Rust in 2017 is coming via the Rust Language Service: an initiative that lets us share a common core of functionality between every editor – from Vim to VS Code and everything in between. In today's episode, I give some background on it and talk about how you can start using it today!

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Tue, 18 Apr 2017 12:17:37 -0600 B9EC7CFA-C988-4EF8-A2F8-299CFE94726F Chris Krycho Where the RLS came from, what it can do, and how you can start using it today! 11:30 full
e020: Putting code in its place https://newrustacean.com/show_notes/e020/ How do we organize code in Rust? Where do we break it apart into modules or crates, and why?

Notes

Structuring code in a language like Rust can seem a bit more ambiguous than doing the same in a language with classes to attach all our functionality to, but in practice, the concerns are much the same: modules are namespaces, and we group by responsibility. In today's episode, I talk through that philosophy (and give some comparisons to other languages), and then look at what it looks like in practice!

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 01 Apr 2017 12:38:33 -0600 44A092E9-78BE-4760-87E2-E94A15DCF5C4 Chris Krycho How do we organize code in Rust? Where do we break it apart into modules or crates, and why? Structuring code in a language like Rust can seem a bit more ambiguous than doing the same in a language with classes to attach all our functionality to, but in practice, the concerns are much the same: modules are namespaces, and we group by *responsibility*. In today's episode, I talk through that philosophy (and give some comparisons to other languages), and then look at what it looks like in practice! 20:20 full
Bonus 8: Giving back (by teaching) https://newrustacean.com/show_notes/bonus/_8/ On the responsibilities and opportunities we have to help others with our knowledge and abilities.

Notes

Many of us have been very blessed with opportunities and support as we learn software. We should go out of our way to share with others in kind. Today, my focus is on teaching, but there are lots of ways to "give back." And I'd love to hear your thoughts and things you're doing in that vein!

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sun, 19 Mar 2017 09:00:00 -0600 5DED2D2B-E06E-44E6-BECC-2A401B40E78A Chris Krycho On the responsibilities and opportunities we have to help others with our knowledge and abilities. Many of us have been very blessed with opportunities and support as we learn software. We should go out of our way to share with others in kind. Today, my focus is on teaching, but there are lots of ways to "give back." And I'd love to hear *your* thoughts and things *you're* doing in that vein! 13:30 full
e019: Let's `Clone` a `Cow` https://newrustacean.com/show_notes/e019/

The final pieces of the story for (single-threaded) memory management in Rust.

Notes

Sometimes, we actually do need to copy types. Wouldn't it be nice if Rust gave us a convenient way to do that when it's convenient, or when the cost is low enough that the ergonomic tradeoffs are worth it? Well, perhaps unsurprisingly, it does! The Copy and Clone traits, plus the Cow type, give us everything we need!

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Tue, 28 Feb 2017 15:20:00 -0700 A39AA3AC-EF1B-41B4-A0A1-F76676A74B1F Chris Krycho The final pieces of the story for (single-threaded) memory management in Rust. Notes ----- Sometimes, we actually do need to copy types. Wouldn't it be nice if Rust gave us a convenient way to do that when it's convenient, or when the cost is low enough that the ergonomic tradeoffs are worth it? Well, perhaps unsurprisingly, it does! The Copy and Clone traits, plus the Cow type, give us everything we need! Sponsors -------- - Aleksey Pirogov - Andreas Fischer - Andrew Thompson - Austin LeSure - Ben Whitley - Charlie Egan - Chris Palmer - Christopher Giffard - Daniel Collin - Derek Morr - Jakub "Limeth" Hlusička - Jordan Henderson - Jupp Müller - Keith Gray - Lachlan Collins - Luca Schmid - Matt Rudder - Matthew Piziak - [Max Jacobson] - Micael Bergeron - Ovidiu Curcan - Pascal Hertleif - Peter Tillemans - Philipp Keller - Ralph Giles ("rillian") - Raph Levien - reddraggone9 - Steven Murawski - Stuart Hinson - Tyler Harper - Vesa Kaihlavirta - Vlad Bezden - William Roe - Zaki (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) ### Become a sponsor - Patreon.com/newrustacean - Venmo.com/chriskrycho - Dwolla](https://www.dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho - Flattr.com/profile/chriskrycho - PayPal.me/chriskrycho Contact ------- - New Rustacean: + Twitter: @newrustacean + Email: hello@newrustacean.com - Chris Krycho + GitHub: chriskrycho + Twitter: @chriskrycho 18:11 full
CYSK: clap https://newrustacean.com/show_notes/cysk/_2/ A Command-Line Argument Parser.

Sponsors

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Tue, 14 Feb 2017 19:33:31 -0700 3666B4E8-5D29-4253-A56D-4145C7372F95 Chris Krycho A Command-Line Argument Parser. Sponsors -------- - Aleksey Pirogov - Andreas Fischer - Andrew Thompson - Austin LeSure - Ben Whitley - Charlie Egan - Chris Palmer - Christopher Giffard - Daniel Collin - Derek Morr - Jakub "Limeth" Hlusička - Jordan Henderson - Jupp Müller - Keith Gray - Lachlan Collins - Luca Schmid - Matt Rudder - Matthew Piziak - [Max Jacobson] - Micael Bergeron - Ovidiu Curcan - Pascal Hertleif - Peter Tillemans - Philipp Keller - Ralph Giles ("rillian") - Raph Levien - reddraggone9 - Steven Murawski - Stuart Hinson - Tyler Harper - Vesa Kaihlavirta - Vlad Bezden - William Roe - Zaki (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) ### Become a sponsor - Patreon.com/newrustacean - Venmo.com/chriskrycho - Dwolla](https://www.dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho - Flattr.com/profile/chriskrycho - PayPal.me/chriskrycho Contact ------- - New Rustacean: + Twitter: @newrustacean + Email: hello@newrustacean.com - Chris Krycho + GitHub: chriskrycho + Twitter: @chriskrycho 10:42 full
e018: `Borrow`, `AsRef`, `Deref`: my head hurts now https://newrustacean.com/show_notes/e018/

Notes

Borrow, AsRef, and Deref are a little complicated, but they're well-worth understanding. Together, they give you tools for dealing with everything from HashMap and friends to conversions involving smart pointer types to easily using String and str or Vec and slice together.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Tue, 31 Jan 2017 16:32:23 -0700 8E739043-E105-4E84-BA22-3835BBB845FC Chris Krycho Three traits which are essential for designing good, Rustic APIs. Notes Borrow, AsRef, and Deref are a little complicated, but they're well-worth understanding. Together, they give you tools for dealing with everything from HashMap and friends to conversions involving smart pointer types to easily using String and str or Vec and slice together. Sponsors * Aleksey Pirogov * Andreas Fischer * Ben Whitley * Cameron Mochrie * Chris Palmer * Christopher Giffard * Daniel Collin * Derek Morr * Jakub &quot;Limeth&quot; Hlusička * Jordan Henderson * Jupp Müller * Keith Gray * Lachlan Collins * Luca Schmid * Matt Rudder * Matthew Piziak * Micael Bergeron * Ovidiu Curcan * Pascal Hertleif * Peter Tillemans * Philipp Keller * Ralph Giles (&quot;rillian&quot;) * Raph Levien * reddraggone9 * Ryan Ollos * Steven Murawski * Vesa Kaihlavirta * Vlad Bezden * William Roe * Zaki (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor * Patreon * Venmo * Dwolla * Cash.me * Flattr * PayPal.me Contact * New Rustacean: * Twitter: @newrustacean * Email: hello@newrustacean.com * Chris Krycho * GitHub: chriskrycho * Twitter: @chriskrycho 17:25 full
CYSK: quick-xml https://newrustacean.com/show_notes/cysk/_1/

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as
well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 09 Jan 2017 07:03:21 -0700 1CF4B00D-9AEC-442B-BD06-A986602D2A56 Chris Krycho A pull-parser for reading and writing XML. Sponsors * Aleksey Pirogov * Andreas Fischer * Ben Whitley * Cameron Mochrie * Chris Palmer * Christopher Giffard * Daniel Collin * Derek Morr * Jakub “Limeth” Hlusička * Jupp Müller * Keith Gray * Lachlan Collins * Luca Schmid * Matt Rudder * Matthew Piziak * Micael Bergeron * Ovidiu Curcan * Pascal Hertleif * Peter Tillemans * Philipp Keller * Ralph Giles (“rillian”) * Raph Levien * reddraggone9 * Ryan Ollos * Steven Murawski * Vesa Kaihlavirta * Vlad Bezden * William Roe * Zaki (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor * Patreon.com/newrustacean * Venmo.com/chriskrycho * Dwolla.com/hub/chriskrycho * Cash.me/$chriskrycho * Flattr.com/chriskrycho * PayPal.me/chriskrycho Contact * New Rustacean: * Twitter: @newrustacean * Email: hello@newrustacean.com * Chris Krycho * GitHub: chriskrycho * Twitter: @chriskrycho 8:38 full
News 2: Let's talk roadmap! https://newrustacean.com/show_notes/news/_2/ Rust’s achievements in 2016 and goals for 2017

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Thu, 29 Dec 2016 12:00:00 -0700 7AAC0E06-6A11-4707-BD9A-AB5AD95F7CBB Chris Krycho Rust’s achievements in 2016 and goals for 2017 Sponsors * Aleksey Pirogov * Andreas Fischer * Ben Whitley * Cameron Mochrie * Chris Palmer * Daniel Collin * Derek Morr * Jakub “Limeth” Hlusička * Jupp Müller * Keith Gray * Lachlan Collins * Luca Schmid * Matt Rudder * Matthew Piziak * Micael Bergeron * Ovidiu Curcan * Pascal Hertleif * Peter Tillemans * Philipp Keller * Ralph Giles (“rillian”) * Raph Levien * reddraggone9 * Ryan Ollos * Steven Murawski * Vesa Kaihlavirta * Vlad Bezden * William Roe * Zaki (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor * Patreon.com/chriskrycho * Venmo.com/chriskrycho * Dwolla.com/hub/chriskrycho * Cash.me/$chriskrycho * Flattr.com/chriskrycho * PayPal.me/chriskrycho Contact * New Rustacean: * Twitter: @newrustacean * Email: hello@newrustacean.com * Chris Krycho * GitHub: chriskrycho * Twitter: @chriskrycho 21:08 full
Meta 1 – Slowing Down https://newrustacean.com/show_notes/meta/_1/ Avoiding burnout by taking it a little easier.

Sometimes, the way a podcast stays in existence is by coming out less often. That’s what’s happening here.

Links

Become a sponsor

Follow

]]>
Sat, 12 Nov 2016 11:26:56 -0700 40FB0537-15C7-475A-94ED-090F9887A358 Chris Krycho Avoiding burnout by taking it a little easier. Sometimes, the way a podcast stays in existence is by coming out less often. That's what's happening here. # Links - [lightning-rs] - [Pelican] - [Hugo] - [Jekyll] - [Static Site Generators]\: The definitive listing of Static Site Generators — all 445 of them! [lightning-rs]: https://github.com/chriskrycho/lightning-rs [Pelican]: http://getpelican.com [Hugo]: https://gohugo.io [Jekyll]: https://jekyllrb.com [Static Site Generators]: https://staticsitegenerators.net # Become a sponsor - Patreon - [Venmo](https://venmo.com/chriskrycho) - [Dwolla](https://www.dwolla.com/hub/chriskrycho) - [Cash.me](https://cash.me/$chriskrycho) # Follow - New Rustacean: + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) - Chris Krycho + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) 7:42 full
Interview 3 – Carol (Nichols || Goulding) https://newrustacean.com/show_notes/interview/_3/

Notes

Chris talks with Carol (Nichols || Goulding), a Rust community team member, co-author of the first major revision of The Rust Programming Language, and co-founder of the first Rust consultancy.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Fri, 30 Sep 2016 06:00:00 -0600 7299496B-086C-450F-94C1-05AB08CDC294 Chris Krycho Carol (Nichols || Goulding) on learning Rust, teaching Rust, and building community Chris talks with Carol (Nichols || Goulding), a Rust community team member, co-author of the first major revision of The Rust Programming Language, and co-founder of the first Rust consultancy. Sponsors * Aleksey Pirogov * Cameron Mochrie * Chris Palmer * Daniel Collin * Derek Morr * Doug Reeves * Hamza Sheikh * Jakub “Limeth” Hlusička * Jupp Müller * Keith Gray * Lachlan Collins * Leif Arne Storset * Luca Schmid * Matthew Piziak * Micael Bergeron * Nils Tekampe * Ovidiu Curcan * Pascal Hertleif * Ralph Giles (“rillian”) * Ralph “FriarTech” Loizzo * Raph Levien * reddraggone9 * Ryan Ollos * Sean Jensen-Gray * Steven Murawski * Vesa Kaihlavirta * William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor * Patreon.com/newrustacean * Venmo.com/newrustacean * Dwolla.com/hub/chriskrycho * Cash.me/$chriskrycho * Flattr.com/profile/chriskrycho * PayPal.me/chriskrycho Contact * New Rustacean: * Twitter: @newrustacean * Email: hello@newrustacean.com * Chris Krycho * GitHub: chriskrycho * Twitter: @chriskrycho 47:11 full
Bonus 7: Katas—or: learning by doing https://newrustacean.com/show_notes/bonus/_7/ Katas—or: learning by doing

Notes

One of the best ways to learn is to pick a small problem you have already internalized, and to do it again but in a new language or in a new way in a language you already know.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 10 Sep 2016 11:50:19 -0600 CEFB964C-E0C9-48FD-9EE6-06A0C1284CC8 Chris Krycho Katas—or: learning by doing One of the best ways to learn is to pick a small problem you have already internalized, and to do it again but in a new language or in a new way in a language you already know. Sponsors * Aleksey Pirogov * Cameron Mochrie * Chris Palmer * Daniel Collin * Derek Morr * Doug Reeves * Hamza Sheikh * Jakub “Limeth” Hlusička * Jupp Müller * Keith Gray * Lachlan Collins * Leif Arne Storset * Luca Schmid * Matthew Piziak * Micael Bergeron * Ovidiu Curcan * Pascal Hertleif * Ralph Giles (“rillian”) * Ralph “FriarTech” Loizzo * Raph Levien * reddraggone9 * Ryan Ollos * Steven Murawski * Vesa Kaihlavirta * William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor * Patreon.com/newrustacean * Venmo.com/chriskrycho * Dwolla.com/hub/chriskrycho * Cash.me/$chriskrych * flattr.com/profile/chriskrycho * PayPal.me/chriskrycho Contact * New Rustacean: * Twitter: @newrustacean * Email: hello@newrustacean.com * Chris Krycho * GitHub: chriskrycho * Twitter: @chriskrycho 10:19 full
Bonus 6: It doesn‘t have to be sexy https://newrustacean.com/show_notes/bonus/_6/ Building (and celebrating) all the little, not-so-glorious pieces of the Rust ecosystem.

Notes

We love the Rust compiler team. But there’s more to the Rust community, and more required for Rust to be as great as it can be, than just the language itself. We need to celebrate other libraries, and even the small ones, just as much (and maybe more) than changes to the language. We need to dig in and work on building the whole ecosystem. (The good news is, we are!)

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 20 Aug 2016 10:15:43 -0600 2B30AB4B-8971-4576-BAD0-953A078B51A3 Chris Krycho Building (and celebrating) all the little, not-so-glorious pieces of the Rust ecosystem. Notes We love the Rust compiler team. But there’s more to the Rust community, and more required for Rust to be as great as it can be, than just the language itself. We need to celebrate other libraries, and even the small ones, just as much (and maybe more) than changes to the language. We need to dig in and work on building the _whole_ ecosystem. (The good news is, we are!) Links - futures-rs - “Zero-cost futures in Rust” - Tokio - “Announcing Tokio” (Carl Lerche on Medium) - “What’s new with ‘The Rust Programming Language’?” - Friends of Rust - ring – Safe, fast, small crypto using Rust - alexa-rs – Rust library for building Alexa skills - gilrs – Game Input Library for Rust Sponsors - Aleksey Pirogov - Cameron Mochrie - Cass Costello - Chris Palmer - Daniel Collin - Derek Morr - Doug Reeves - Eric Fulmer - Hamza Sheikh - Jakub “Limeth” Hlusička - Jared Smith - Keith Gray - Lachlan Collins - Leif Arne Storset - Luca Schmid - Micael Bergeron - Pascal Hertleif - Ralph Giles (“rillian”) - Ralph “FriarTech” Loizzo - Raph Levien - reddraggone9 - Ryan Ollos - Steven Murawski - Vesa Kaihlavirta - William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor - Patreon.com/newrustacean - Venmo.com/chriskrycho - Dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho - flattr.com/profile/chriskrycho - PayPal.me/chriskrycho Contact - New Rustacean: - Twitter: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - GitHub: chriskrycho - Twitter: @chriskrycho 11:27 full
e017: Point me where I need to go https://newrustacean.com/show_notes/e017/ A deep dive on references and pointers in Rust.

Notes

By listener request, today we look at the syntax and semantics of referencing and dereferencing and the corresponding & and * operators.

As was the case with e016, the code samples have little to say in their documentation; reading the code will be necessary for seeing the ideas.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 08 Aug 2016 14:35:00 -0600 3FD4B9E5-7496-4FCB-AD95-829A6A295274 Chris Krycho A deep dive on references and pointers in Rust. Notes By listener request, today we look at the syntax and semantics of referencing and dereferencing and the corresponding `&` and `*` operators. As was the case with e016, the code samples have little to say in their documentation; reading the code will be necessary for seeing the ideas. Sponsors * Aleksey Pirogue * Cameron Mochrie * Chris Palmer * Daniel Collin * Derek Morr * Doug Reeves * Eric Fulmer * Hamza Sheikh * Jakub “Limeth” Hlusička * Jared Smith * Keith Gray * Lachlan Collins * Leif Arne Storset * Luca Schmid * Micael Bergeron * Pascal Hertleif * Ralph Giles (“gillian”) * Ralph “FriarTech” Loizzo * Raph Levien * reddraggone9 * Ryan Oleos * Steven Murawski * Vesa Kaihlavirta * William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor * Patreon.com/newrustacean * Venmo.com/chriskrycho * Dwolla.com/hub/chriskrycho * Cash.me/$chriskrych * flattr.com/profile/chriskrycho * PayPal.me/chriskrycho Contact * New Rustacean: * Twitter: @newrustacean * Email: hello@newrustacean.com * Chris Krycho * GitHub: chriskrycho * Twitter: @chriskrycho 17:06 full
e016: RefCells and code smells https://newrustacean.com/show_notes/e016/ Digging deeper on smart pointers and mutability with Cell and RefCell.

Notes

What are the Cell and RefCell types, and when should we use them?

Today, we follow up both the detailed discussion of smart pointers in e015 and the closely related discussion in Interview 2 with Raph Levien, and look at two types you need to have a good idea how to deal with if you want to use these smart pointer types more ergonomically—that is, how to use them without feeling like you’re beating your head against a wall!

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Sat, 23 Jul 2016 11:58:33 -0600 391443C9-2019-4843-BEB3-46B5140C6256 Chris Krycho Digging deeper on smart pointers and mutability with `Cell` and `RefCell`. Notes What are the Cell and RefCell types, and when should we use them? Today, we follow up both the detailed discussion of smart pointers in e015 and the closely related discussion in Interview 2 with Raph Levien, and look at two types you need to have a good idea how to deal with if you want to use these smart pointer types more _ergonomically_—that is, how to use them without feeling like you’re beating your head against a wall! Sponsors - Aleksey Pirogov - Chris Palmer - Daniel Collin - Derek Morr - Doug Reeves - Eric Fulmer - Hamza Sheikh - Jakub “Limeth” Hlusička - Keith Gray - Lachlan Collins - Leif Arne Storset - Luca Schmid - Micael Bergeron - Michael Clayton - Pascal Hertleif - Ralph Giles (“rillian”) - Ralph “FriarTech” Loizzo - Raph Levien - reddraggone9 - Ryan Ollos - Vesa Kaihlavirta - William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor - Patreon.com/newrustacean - Venmo.com/chriskrycho - Dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho - flattr.com/profile/chriskrycho - PayPal.me/chriskrycho Contact - New Rustacean: - Twitter: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - GitHub: chriskrycho - Twitter: @chriskrycho 18:52 full
Interview 2::Part 2 – Raph Levien https://newrustacean.com/show_notes/interview/_2/part_2/ Raph Levien on Rust’s current strengths and places it can improve

Notes

Chris chats with Raph Levien about what inspired him to build a text editor, as well as about where the rough edges in the Rust development story are today, and how we might improve them going forward.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 04 Jul 2016 17:35:00 -0600 E2C1612A-178F-4AAF-8581-FC589BC3345E Chris Krycho Raph Levien on Rust’s current strengths and places it can improve Notes Chris chats with Raph Levien about what inspired him to build a text editor, as well as about where the rough edges in the Rust development story are today, and how we might improve them going forward. Sponsors - Aleksey Pirogov - Chris Palmer - Daniel Collin - Derek Morr - Doug Reeves - Hamza Sheikh - Keith Gray - Lachlan Collins - Leif Arne Storset - Luca Schmid - Micael Bergeron - Pascal Hertleif - Ralph Giles (“rillian”) - Ralph “FriarTech” Loizzo - Raph Levien - reddraggone9 - Ryan Ollos - Vesa Kaihlavirta - William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor - Patreon.com/newrustacean - Venmo.com/chriskrycho - Dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho - flattr.com/profile/chriskrycho - PayPal.me/chriskrycho Contact - New Rustacean: - Twitter: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - GitHub: chriskrycho - Twitter: @chriskrycho 19:33 full
Interview 2::Part 1 – Raph Levien https://newrustacean.com/show_notes/interview/_2/part_1/ Raph Levien on using Rust to build the Xi editor

Notes

Chris chats with Raph Levien about his background in software development, what attracted him to Rust, and how he’s using Rust to build the Xi Editor, a project which aims to be the fastest text editor out there, with native user interfaces and a Rust text engine.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Fri, 24 Jun 2016 19:26:51 -0600 E585DC9C-567B-4902-B722-AF4D24DCA256 Chris Krycho Raph Levien on using Rust to build the Xi editor Notes Chris chats with Raph Levien about his background in software development, what attracted him to Rust, and how he’s using Rust to build the Xi Editor, a project which aims to be the fastest text editor out there, with native user interfaces and a Rust text engine. Sponsors - Aleksey Pirogov - Chris Palmer - Daniel Collin - Derek Morr - Doug Reeves - Hamza Sheikh - Lachlan Collins - Leif Arne Storset - Luca Schmid - Micael Bergeron - Pascal Hertleif - Ralph Giles (“rillian”) - Ralph “FriarTech” Loizzo - Raph Levien - reddraggone9 - Ryan Ollos - Vesa Kaihlavirta - William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor - Patreon.com/newrustacean - Venmo.com/chriskrycho - Dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho - flattr.com/profile/chriskrycho - PayPal.me/chriskrycho Contact - New Rustacean: - Twitter: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - GitHub: chriskrycho - Twitter: @chriskrycho 28:17 full
e015: Not dumb pointers https://newrustacean.com/show_notes/e015/ Box, String, Vec, Rc, and Arc have this in common: they’re not dumb.

This episode, we take a close look at smart pointer types—from a few we’ve already talked about, like Box, Vec, and String, to some new ones, like Rc and Arc.

  • What smart pointers are, and what makes them ‘smart’.
  • Why we want or need smart pointers.
  • A bit about Box.
  • A lot more about Rc and Arc.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Fri, 17 Jun 2016 18:07:22 -0600 DE71BD86-2409-4D8A-8A5A-797751339FC1 Chris Krycho Box, String, Vec, Rc, and Arc have this in common: they’re not dumb. This episode, we take a close look at smart pointer types—from a few we’ve already talked about, like Box, Vec, and String, to some new ones, like Rc and Arc. - What smart pointers are, and what makes them ‘smart’. - Why we want or need smart pointers. - A bit about Box. - A lot more about Rc and Arc. Sponsors - Aleksey Pirogov - Chris Palmer - Daniel Collin - Derek Morr - Doug Reeves - Hamza Sheikh - Lachlan Collins - Leif Arne Storset - Luca Schmid - Micael Bergeron - Pascal Hertleif - Ralph Giles (“rillian”) - Ralph “FriarTech” Loizzo - Raph Levien - reddraggone9 - Ryan Ollos - Vesa Kaihlavirta - William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Contact - New Rustacean: - Twitter: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - GitHub: chriskrycho - Twitter: @chriskrycho 20:03 full
News 1: One year and counting https://newrustacean.com/show_notes/news/_1/ A year in, Rust is changing fast but still stable.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Tue, 31 May 2016 12:13:25 -0600 A8D6E44A-007D-4D36-9442-AA30722DF454 Chris Krycho A year in, Rust is changing fast but still stable. Sponsors * Aleksey Pirogue * Chris Palmer * Daniel Collin * Derek Morr * Hamza Sheikh * Lachlan Collins * Leif Arne Storset * Luca Schmid * Micael Bergeron * Pascal Hertleif * Ralph Giles (“gillian”) * Ralph “FriarTech” Loizzo * reddraggone9 * Ryan Oleos * Vesa Kaihlavirta * William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor * Patreon.com/newrustacean * Venmo.com/chriskrycho * Dwolla.com/hub/chriskrycho * Cash.me/$chriskrycho * Flattr.com/profile/chriskrycho * PayPal.me/chriskrycho Contact * New Rustacean: * Twitter: @newrustacean * Email: hello@newrustacean.com * Chris Krycho * GitHub: chriskrycho * Twitter: @chriskrycho 26:16 full
Bonus 5: Better than open-source contributions https://newrustacean.com/show_notes/bonus/_5/ Some things matter more than contributing to open-source software in your free time. A lot more.

It’s trendy to ask for open-source work as evidence of your interest in tech and commitment to software development. Trendy and completely wrong. Companies should not demand open-source contributions from their employees, and beyond that, should learn to recognize that profit is not the most valuable thing in the world. People are.

Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 09 May 2016 19:47:24 -0600 B75ECD4A-1A69-4BF1-A5D0-8F860A3DDFF4 Chris Krycho Some things matter more than contributing to open-source software in your free time. A lot more. It’s trendy to ask for open-source work as evidence of your interest in tech and commitment to software development. Trendy and completely wrong. Companies should not demand open-source contributions from their employees, and beyond that, should learn to recognize that profit is not the most valuable thing in the world. People are. Sponsors * Aleksey Pirogue * Chris Palmer * Daniel Collin * Derek Morr * Hamza Sheikh * Lachlan Collins * Leif Arne Storset * Luca Schmid * Micael Bergeron * Pascal Hertleif * Ralph Giles (‚Äúrillian‚Äù) * Ralph ‚ÄúFriarTech‚Äù Loizzo * reddraggone9 * Ryan Oleos * Vesa Kaihlavirta * William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor * Patreon.com/newrustacean * Venmo.com/chriskrycho * Dwolla.com/hub/chriskrycho * Cash.me/$chriskrycho * Flattr.com/profile/chriskrycho * PayPal.me/chriskrycho Contact * New Rustacean: @newrustacean or hello@newrustacean.com * Chris Krycho: github.com/chriskrycho, @chriskrycho 11:07 full
e014: Stringing things along https://newrustacean.com/show_notes/e014/ Strings &strs and Vecs and slices (and Unicode) – oh, my!

Notes

This episode, I take a deep dive on strings in Rust, looking at the differences between String and &str, discussing Unicode a bit, and then expanding the discussion to think about how these types relate to the types they’re built on (like Vec).

Sponsors

  • Aleksey Pirogov
  • Chris Palmer
  • Derek Morr
  • Hamza Sheikh
  • Lachlan Collins
  • Leif Arne Storset
  • Luca Schmid
  • Micael Bergeron
  • Pascal Hertleif
  • Ralph Giles (“rillian”)
  • Ralph “FriarTech” Loizzo
  • reddraggone9
  • Ryan Ollos
  • Vesa Kaihlavirta
  • William Roe

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 25 Apr 2016 20:16:03 -0600 50D3DAF8-7B5C-4B19-A6DE-E2CFD21F075F Chris Krycho Strings &strs and Vecs and slices (and Unicode) – oh, my! Notes This episode, I take a deep dive on strings in Rust, looking at the differences between String and &str, discussing Unicode a bit, and then expanding the discussion to think about how these types relate to the types they’re built on (like Vec). Links - Strings: - The Rust Book - Rust by Example - str docs: - module - primitive type - String - module - type definition - Dereferencing - coercions - std::ops::Deref Sponsors - Aleksey Pirogov - Chris Palmer - Derek Morr - Hamza Sheikh - Lachlan Collins - Leif Arne Storset - Luca Schmid - Micael Bergeron - Pascal Hertleif - Ralph Giles (“rillian”) - Ralph “FriarTech” Loizzo - reddraggone9 - Ryan Ollos - Vesa Kaihlavirta - William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor - Patreon.com/chriskrycho - Venmo.com/chriskrycho - Dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho - Flattr.com/profile/chriskrycho Contact - New Rustacean: - Twitter: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - GitHub: chriskrycho - Twitter: @chriskrycho 18:58 full
Bonus 4: We can have nice things https://newrustacean.com/show_notes/bonus/_4/ Just how good Rust is, and how you can learn it even if you’re busy.

Notes

Sometimes life goes crazy and I don’t have time to do all the technical writing required for a full episode, but I can’t get Rust off my mind, so I record an episode like this one. Where I talk a bit about how versatile Rust is and suggest some surprising ways you might be able to use it.

Sponsors

  • Aleksey Pirogov
  • Chris Palmer
  • Derek Morr
  • Hamza Sheikh
  • Lachlan Collins
  • Leif Arne Storset
  • Luca Schmid
  • Micael Bergeron
  • Pascal Hertleif
  • Ralph Giles (“rillian”)
  • Ralph “FriarTech” Loizzo
  • reddraggone9
  • Ryan Ollos
  • Vesa Kaihlavirta
  • William Roe

(Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!)

Become a sponsor

Contact

]]>
Tue, 19 Apr 2016 05:50:00 -0600 38DF55F2-94FB-4CA0-8212-9C4D2897167F Just how good Rust is, and how you can learn it even if you’re busy. Just how good Rust is, and how you can learn it even if you’re busy. Notes Sometimes life goes crazy and I don’t have time to do all the technical writing required for a full episode, but I can’t get Rust off my mind, so I record an episode like this one. Where I talk a bit about how versatile Rust is and suggest some surprising ways you might be able to use it. Sponsors * Aleksey Pirogue * Chris Palmer * Derek Morr * Hamza Sheikh * Lachlan Collins * Leif Arne Storset * Luca Schmid * Micael Bergeron * Pascal Hertleif * Ralph Giles (“gillian”) * Ralph “FriarTech” Loizzo * reddraggone9 * Ryan Oleos * Vesa Kaihlavirta * William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor * Patreon * Venom * Dwolla * Cash.me Contact * New Rustacean: * Twitter: @newrustacean * Email: hello@newrustacean.com * Chris Krycho * GitHub: chriskrycho * Twitter: @chriskrycho 10:17 full
e013: Staying alive https://newrustacean.com/show_notes/e013/ Reasoning about and using lifetimes in Rust (and why we need them)

Notes

Lifetimes are our way of reasoning about how long a given piece of data is
available and safe to use in Rust. The reason we don't have the dangling
pointer problem is that we do have lifetimes instead. They're not magic,
they're just a bit of semantics and syntax that let us specify the rules for
how long any given item lives, and how long references to data must be valid.

Links


Sponsors

(Thanks to the couple people donating who opted out of the reward tier, as
well. You know who you are!)

Become a sponsor

Contact

]]>
Mon, 04 Apr 2016 17:52:21 -0600 20F0A4EE-7D88-4C90-8BA5-7D28FB8AF0AD Chris Krycho Reasoning about and using lifetimes in Rust (and why we need them) Notes Lifetimes are our way of reasoning about how long a given piece of data is available and safe to use in Rust. The reason we don't have the dangling pointer problem is that we do have lifetimes instead. They're not magic, they're just a bit of semantics and syntax that let us specify the rules for how long any given item lives, and how long references to data must be valid. Sponsors * Aleksey Pirogue * Chris Palmer * Derek Morr * Hamza Sheikh * Lachlan Collins * Leif Arne Storset * Luca Schmid * Micael Bergeron * Pascal Hertleif * Ralph Giles ("gillian") * Ralph "FriarTech" Loizzo * reddraggone9 * Ryan Oleos * Vesa Kaihlavirta * William Roe (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) Become a sponsor * Patreon.com/newrustacean * Venmo.com/chriskrycho * Dwolla.com/hub/chriskrycho * Cash.me/$chriskrycho Contact * New Rustacean: * Twitter: @newrustacean * Email: hello@newrustacean.com * Chris Krycho * GitHub: chriskrycho * Twitter: @chriskrycho 17:40 full
e012: I'm not familiar with that expression https://newrustacean.com/show_notes/e012/ What it means to be an expression-oriented language, and how that works out in Rust.

Notes

Rust is an expression-oriented language. What does that mean, and how does it play out in Rust? We look at if and match blocks, discuss looping constructs, and examine functions, and then widen out to discuss how having an expression-oriented language can change the way we think about programming.

Sponsors

  • Aleksey Pirogov
  • Chris Palmer
  • Derek Morr
  • Hamza Sheikh
  • Lachlan Collins
  • Leif Arne Storset
  • Luca Schmid
  • Micael Bergeron
  • Pascal
  • Ralph Giles (“rillian”)
  • Ralph “FriarTech” Loizzo
  • reddraggone9
  • Ryan Ollos
  • William Roe

Become a sponsor

Contact

]]>
Mon, 21 Mar 2016 05:00:00 -0600 301B3967-5003-4D65-8ED6-D4594C2832F8 Chris Krycho What it means to be an expression-oriented language, and how that works out in Rust. Notes Rust is an expression-oriented language. What does that mean, and how does it play out in Rust? We look at if and match blocks, discuss looping constructs, and examine functions, and then widen out to discuss how having an expression-oriented language can change the way we think about programming. Sponsors * Aleksey Pirogue * Chris Palmer * Derek Morr * Hamza Sheikh * Lachlan Collins * Leif Arne Storset * Luca Schmid * Micael Bergeron * Pascal * Ralph Giles (“gillian”) * Ralph “FriarTech” Loizzo * reddraggone9 * Ryan Oleos * William Roe Become a sponsor * Patreon.com/newrustacean * Venmo.com/chriskrycho * Dwolla.com/hub/chriskrycho * Cash.me/$chriskrycho Contact * New Rustacean: - Twitter: @newrustacean - Email: hello@newrustacean.com * Chris Krycho - GitHub: chriskrycho - Twitter: @chriskrycho 16:41 full
e011: Once Upon a Type https://newrustacean.com/show_notes/e011/ Type systems: strong vs. weak, dynamic vs. static, and degrees of expressivity.

Notes

Talking about type systems! A broad and wide-ranging discussion about type systems in general, with specific examples from languages like PHP, JavaScript, Python, C, C++, Java, C♯, Haskell, and Rust!

  • What is a type system?
  • What are the kinds of things we get out of type systems?
  • What are the tradeoffs with different type systems?
  • What is Rust’s type system like?
  • What is especially attractive about Rust’s type system?

A comment on the C integer/character string addition example: what’s actually happening there is that the character string is an array “under the covers,” and as such has an address. C silently switches to using the memory address, which is of course just an integer, when you try to add the two together. As I said on the show: the result is nonsense (unless you’re using this as a way of operating on memory addresses), but it’s compileable nonsense. In a stricter and stronger type system, memory addresses and normal numbers shouldn’t be addable!

Sponsors

  • Aleksey Pirogov
  • Chris Palmer
  • Derek Morr
  • Hamza Sheikh
  • Lachlan Collins
  • Leif Arne Storset
  • Luca Schmid
  • Micael Bergeron
  • Pascal
  • Ralph Giles (“rillian”)
  • Ralph “FriarTech” Loizzo
  • reddraggone9
  • Ryan Ollos
  • William Roe

Become a sponsor

Contact

]]>
Tue, 08 Mar 2016 08:00:00 -0700 AC4E31F9-5811-4B6E-86E2-5E3ED3CE8DEF Chris Krycho Type systems: strong vs. weak, dynamic vs. static, and degrees of expressivity. Notes Talking about type systems! A broad and wide-ranging discussion about type systems in general, with specific examples from languages like PHP, JavaScript, Python, C, C++, Java, C♯, Haskell, and Rust! * What is a type system? * What are the kinds of things we get out of type systems? * What are the tradeoffs with different type systems? * What is Rust’s type system like? * What is especially attractive about Rust’s type system? A comment on the C integer/character string addition example: what’s actually happening there is that the character string is an array “under the covers,” and as such has an address. C silently switches to using the memory address, which is of course just an integer, when you try to add the two together. As I said on the show: the result is nonsense (unless you’re using this as a way of operating on memory addresses), but it’s compellable nonsense. In a stricter and stronger type system, memory addresses and normal numbers shouldn’t be addable! Sponsors * Aleksey Pirogue * Chris Palmer * Derek Morr * Hamza Sheikh * Lachlan Collins * Leif Arne Storset * Luca Schmid * Micael Bergeron * Pascal * Ralph Giles (“gillian”) * Ralph “FriarTech” Loizzo * reddraggone9 * Ryan Oleos * William Roe Become a sponsor * Patreon.com/newrustacean * Venmo.com/chriskrycho * Dwolla.com/hub/chriskrycho * Cash.me/$chriskrycho Contact * New Rustacean: - Twitter: @newrustacean - Email: hello@newrustacean.com * Chris Krycho - GitHub: chriskrycho - Twitter: @chriskrycho 17:51 full
Interview 1::Part 2 – Sean Griffin https://newrustacean.com/show_notes/interview/_1/part_2/ Sean Griffin on type systems and hopes for Rust's future

Notes

Chris chats with Sean Griffin about the tradeoffs between mental overhead and type safety, the expressiveness of different type systems, and some of the places where Rust currently falls down.

Corrigenda

Sean noted he could be wrong about IEnumerable<T> not having a Sum method in C♯, and post-show research indicated that he was (it's possible it was added after he had stopped doing .NET work, of course). See the documentation for details on how IEnumerable<T>.Sum it behaves in C♯ if you're curious.

As a related note, I (Chris) have done a little bit of digging on C♯ in the interval and it's fair to say that while a lot of the "ceremony" involved in writing C♯ is annoying, it's much more than just a "slightly nicer Java", and indeed is a much nicer language than my previous, limited exposure had led me to believe. It's no Rust or F♯, but its type system is substantially more capable than Java's.

Links

Sponsors

  • Aleksey Pirogov
  • Chris Palmer
  • Derek Morr
  • Hamza Sheikh
  • Leif Arne Storset
  • Luca Schmid
  • Micael Bergeron
  • Ralph Giles ("rillian")
  • reddraggone9
  • Ryan Ollos
  • William Roe

Become a sponsor

Follow

]]>
Thu, 25 Feb 2016 06:30:00 -0700 EF51E282-74DB-4F9F-8952-DBF70B1F8B2E Chris Krycho Sean Griffin on type systems and hopes for Rust's future Notes ----- Chris chats with Sean Griffin about the tradeoffs between mental overhead and type safety, the expressiveness of different type systems, and some of the places where Rust currently falls down. ### Corrigenda Sean noted he could be wrong about `IEnumerable<T>` not having a `Sum` method in C♯, and post-show research indicated that he was (it's possible it was added after he had stopped doing .NET work, of course). See the [documentation][c1] for details on how `IEnumerable<T>.Sum` it behaves in C♯ if you're curious. As a related note, I (Chris) have done a little bit of digging on C♯ in the interval and it's fair to say that while a lot of the "ceremony" involved in writing C♯ is annoying, it's much more than just a "slightly nicer Java", and indeed is a much nicer language than my previous, limited exposure had led me to believe. It's no Rust or F♯, but its type system is substantially more capable than Java's. [c1]: https://msdn.microsoft.com/library/bb919210(v=vs.90).aspx Links ----- - fmap + [Discussion of `fmap` with `Optional` in Swift][l1] + [In Haskell][l2] - Rust: + [Trait objects][l3] + [Specialization RFC][l4] * [Implementation][l5] - [Diesel][l6] [l1]: https://robots.thoughtbot.com/functional-swift-for-dealing-with-optional-values [l2]: http://learnyouahaskell.com/functors-applicative-functors-and-monoids [l3]: https://doc.rust-lang.org/book/trait-objects.html [l4]: https://github.com/rust-lang/rfcs/pull/1210 [l5]: https://github.com/rust-lang/rust/issues/31844 [l6]: https://github.com/sgrif/diesel Sponsors -------- - Aleksey Pirogov - Chris Palmer - [Derek Morr][s3] - Hamza Sheikh - Leif Arne Storset - Luca Schmid - Micael Bergeron - Ralph Giles ("rillian") - reddraggone9 - Ryan Ollos - [William Roe][s11] [s3]: https://twitter.com/derekmorr [s11]: http://willroe.me ### Become a sponsor - Patreon - [Venmo](https://venmo.com/chriskrycho) - [Dwolla](https://www.dwolla.com/hub/chriskrycho) - [Cash.me](https://cash.me/$chriskrycho) Follow ------ - New Rustacean: + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) - Chris Krycho + GitHub: [chriskrycho](https://github.com/chriskrycho) + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) 22:14 full
Interview 1::Part 1 – Sean Griffin https://newrustacean.com/show_notes/interview/_1/part_1/ Sean Griffin on Rust, ORMs, and Web Frameworks

Notes

Chris chats with Sean Griffin about his programming background and initial experience with Rust, Rust's appeal, and what he's doing with Diesel and some of his plans for a new web framework in Rust.

Links

Sponsors

  • Aleksey Pirogov
  • Chris Palmer
  • Derek Morr
  • Hamza Sheikh
  • Leif Arne Storset
  • Luca Schmid
  • Micael Bergeron
  • Ralph Giles ("rillian")
  • reddraggone9
  • Ryan Ollos
  • William Roe

Become a sponsor

Follow

]]>
Mon, 15 Feb 2016 13:00:00 -0700 2FDF4C7A-DEC9-4642-A5FB-99D1D6726527 Chris Krycho Sean Griffin on Rust, Diesel, and ORMs Notes Chris chats with Sean Griffin about his programming background and initial experience with Rust, Rust’s appeal, and what he’s doing with Diesel and some of his plans for a new web framework in Rust. Sponsors - Aleksey Pirogov - Chris Palmer - Derek Morr - Hamza Sheikh - Leif Arne Storset - Luca Schmid - Micael Bergeron - Ralph Giles (“rillian”) - reddraggone9 - Ryan Ollos - William Roe Become a sponsor - Patreon - Venmo - Dwolla - Cash.me Follow - New Rustacean: - Twitter: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - GitHub: chriskrycho - Twitter: @chriskrycho 24:50 full
Bonus 3: Building as a community https://newrustacean.com/show_notes/bonus/_3/ Community is one of the most important parts of a programming language community, or indeed any technical community. In this episode, I talk a bit about what happens when you don't have a good community, how Rust's community has done well so far, and then how to keep building a good community and how to build good things as a community.

Sponsors

  • Aleksey Pirogov
  • Chris Palmer
  • Derek Morr
  • Hamza Sheikh
  • Luca Schmid
  • Micael Bergeron
  • Ralph Giles (“rillian”)
  • reddraggone9
  • William Roe

Become a sponsor

Follow

]]>
Sun, 31 Jan 2016 17:08:36 -0700 E1508C29-D386-4AC2-AACD-10B6C716CDCC Chris Krycho The value of a good community, and how you can help Rust today. Community is one of the most important parts of a programming language community, or indeed *any* technical community. In this episode, I talk a bit about what happens when you don't have a good community, how Rust's community has done well so far, and then how to keep building a good community and how to build good things *as* a community. Sponsors - Aleksey Pirogov - Chris Palmer - Derek Morr - Hamza Sheikh - Luca Schmid - Micael Bergeron - Ralph Giles (“rillian”) - reddraggone9 - William Roe Become a sponsor - Patreon.com/newrustacean - Venmo.com/chriskrycho - Dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho Follow - New Rustacean: - Twitter: @newrustacean - App.net: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - Twitter: @chriskrycho - App.net: @chriskrycho 12:03 full
e010: Macros rule! https://newrustacean.com/show_notes/e010/ Macros rule!

Notes

Because of the way macros are exported—before name resolution on crates occurs—the documentation for the macros defined in the source for this episode occurs in the Macros section of the show_notes crate documentation, rather than within the documentation for this module. (See the Rust Book discussion of documenting macros for details.) Even so, the source is still in this module; see the implementations for details.

Sponsors

  • Aleksey Pirogov
  • Chris Palmer
  • Derek Morr
  • Hamza Sheikh
  • Luca Schmid
  • Micael Bergeron
  • Ralph Giles (“rillian”)
  • reddraggone9
  • William Roe

Become a sponsor

Follow

]]>
Mon, 18 Jan 2016 08:25:00 -0700 https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e010.mp3 Chris Krycho Using Rust's macro system, its limitations, and its future. Using Rust's macro system, its limitations, and its future. Because of the way macros are exported—before name resolution on crates occurs—the documentation for the macros defined in the source for this episode occurs in the MACROS section of the show_notes crate documentation, rather than within the documentation for this module. (See the Rust Book discussion of documenting macros for details.) Even so, the source is still in this module; see the implementations for details. Sponsors - Aleksey Pirogov - Chris Palmer - Derek Morr - Hamza Sheikh - Luca Schmid - Micael Bergeron - Ralph Giles (“rillian”) - reddraggone9 - William Roe Become a sponsor - Patreon.com/newrustacean - Venmo.com/chriskrycho - Dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho Follow - New Rustacean: - Twitter: @newrustacean - App.net: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - Twitter: @chriskrycho - App.net: @chriskrycho 16:32 full
e009: Composing a Rustic tune https://newrustacean.com/show_notes/e009/ Notes

Last time, we looked at generics and traits at a high level. This time, we dig deeper on traits, looking specifically at std::iter::Iterator as an example of a powerful trait that can be composed across types, and then at how we might compose multiple traits on a single type.

We also talk about the syntax for traits, the use of marker traits, some of the things you can’t presently do with traits, and even just a smidge about the future of traits in Rust. All that in less than 20 minutes!

You’ll find today’s source example fairly interesting, I think: it’s just one type, but it uses almost every concept discussed on the show today!

Sponsors

  • Aleksey Pirogov
  • Chris Palmer
  • Derek Morr
  • Hamza Sheikh
  • Luca Schmid
  • Micael Bergeron
  • Ralph Giles (“rillian”)
  • reddraggone9
  • William Roe

Become a sponsor

Follow

]]>
Sat, 09 Jan 2016 14:00:11 -0700 505802A1-4F58-4C3C-A268-B1354B5B2F8E Chris Krycho Getting into the nitty-gritty with Rust's traits. Notes Last time, we looked at generics and traits at a high level. This time, we dig deeper on traits, looking specifically at std::iter::Iterator as an example of a powerful trait that can be composed across types, and then at how we might compose multiple traits on a single type. We also talk about the syntax for traits, the use of marker traits, some of the things you _can’t_ presently do with traits, and even just a smidge about the _future_ of traits in Rust. All that in less than 20 minutes! You’ll find today’s source example fairly interesting, I think: it’s just one type, but it uses almost every concept discussed on the show today! Links - Nick Cameron: “Thoughts on Rust in 2016” - “Upcoming breakage starting in Rust 1.7, from RFCs 1214 and 136” - RFC 1214: Clarify (and improve) rules for projections and well-formedness - RFC 136: Ban private items in public APIs - The Rust Book: - Traits - Trait objects (dynamic dispatch) - The Rust reference: - std::iter and std::iter::Iterator - Add - Drop - PartialEq and Eq - PartialOrd and Ord - Special traits - Trait objects - RFC: impl specialization - Aaron Turon: “Specialize to reuse” Sponsors - Aleksey Pirogov - Chris Palmer - Derek Morr - Hamza Sheikh - Luca Schmid - Micael Bergeron - Ralph Giles (“rillian”) - reddraggone9 - William Roe Become a sponsor - Patreon.com/newrustacean - Venmo.com/chriskrycho - Dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho Follow - New Rustacean: - Twitter: @newrustacean - App.net: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - Twitter: @chriskrycho - App.net: @chriskrycho 17:23 full
e008: Just like something else https://newrustacean.com/show_notes/e008/ Notes

In this episode we cover—at a very high level—two more fundamental concepts in Rust programming: generics and traits.

Generics gives us the abilitty to write types and functions which can be used with more than one type. Traits give us the ability to specify behavior which can be implemented for more than one type. The combination gives us powerful tools for higher-level programming constructs in Rust.

Comments on source code

Now that we have a handle on how tests work, we’ll use them to validate the behavior of our code going forward. This is great: we can show that the tests do what we think.

To today’s point, though: we actually know even apart from whether the tests run successfully that these generic functions and the associated traits are behaving as we want. Failure with generics is a compile-time error, not a runtime error.

Sponsors

  • Chris Palmer
  • Derek Morr
  • Luca Schmid
  • Micael Bergeron
  • Ralph Giles (“rillian”)
  • reddraggone9
  • William Roe

Become a sponsor

Follow

]]>
Sun, 27 Dec 2015 09:19:47 -0700 C41DFF97-B4A0-4A50-89AF-4803FD50B547 Chris Krycho Generics, traits, and shared behavior in Rust. Notes In this episode we cover—at a _very_ high level—two more fundamental concepts in Rust programming: generics and traits. Generics gives us the abilitty to write types and functions which can be used with more than one type. Traits give us the ability to specify behavior which can be implemented for more than one type. The combination gives us powerful tools for higher-level programming constructs in Rust. Comments on source code Now that we have a handle on how tests work, we’ll use them to validate the behavior of our code going forward. This is great: we can show that the tests do what we think. To today’s point, though: we actually know even apart from whether the tests _run_ successfully that these generic functions and the associated traits are behaving as we want. Failure with generics is a _compile_-time error, not a runtime error. Sponsors - Chris Palmer - Derek Morr - Luca Schmid - Micael Bergeron - Ralph Giles (“rillian”) - reddraggone9 - William Roe Become a sponsor - Patreon/newrustacean - Venmo.com/chriskrycho - Dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho Follow - New Rustacean: - Twitter: @newrustacean - App.net: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - Twitter: @chriskrycho - App.net: @chriskrycho 17:37 full
e007: Testify https://newrustacean.com/show_notes/e007/ Notes

All about testing in Rust! In order, we take a look at:

  • Why you need tests.
  • Unit tests in other (dynamically-typed) languages vs. in Rust.
  • How to write unit tests in Rust.
  • How and why to write integration tests in Rust.
  • How and why to use benchmarks in Rust.

The detailed code samples for this episode are heavy on showing; because of the nature of test functions, you will be best off just reading the source rather than leaning heavily on the descriptions generated by rustdoc. (The descriptions are still there, but they’re much less useful than they have been in previous episodes.) In particular, the test module here is excluded because of the use of the #[cfg(test)] attribute marker on it.

Because we are using the feature-gated benchmarking functionality, the show notes “library” can now only be compiled with the Rust nightly (as of 1.5, the version current as this episode is produced).

One thing that isn’t necessarily obvious from reading the test documentation in the Rust book and Rust reference: the extern crate test statement needs to be not in this module, but at the module (lib.rs) which defines the library/crate; in this case, show_notes/lib.rs.

Sponsors

  • Chris Palmer
  • Derek Morr
  • Luca Schmid
  • Micael Bergeron
  • Ralph Giles (“rillian”)
  • reddraggone9
  • William Roe

Become a sponsor

Follow

]]>
Sun, 13 Dec 2015 10:38:36 -0700 9B3A138D-FE96-4A8A-A708-BDCBF1F63A3F Chris Krycho Testing and benchmarking, and compiler attributes. Notes All about testing in Rust! In order, we take a look at: - Why you need tests. - Unit tests in other (dynamically-typed) languages vs. in Rust. - How to write unit tests in Rust. - How and why to write integration tests in Rust. - How and why to use benchmarks in Rust. The detailed code samples for this episode are heavy on showing; because of the nature of test functions, you will be best off just reading the source rather than leaning heavily on the descriptions generated by RUSTDOC. (The descriptions are still _there_, but they’re much less useful than they have been in previous episodes.) In particular, the test module here is excluded because of the use of the #[cfg(test)] attribute marker on it. Because we are using the feature-gated benchmarking functionality, the show notes “library” can now only be compiled with the Rust nightly (as of 1.5, the version current as this episode is produced). One thing that isn’t necessarily obvious from reading the test documentation in the Rust book and Rust reference: the extern crate test statement needs to be not in this module, but at the module (lib.rs) which defines the library/crate; in this case, show_notes/lib.rs. Sponsors - Chris Palmer - Derek Morr - Luca Schmid - Micael Bergeron - Ralph Giles (“rillian”) - reddraggone9 - William Roe Become a sponsor - Patreon.com/newrustacean - Venmo.com/chriskrycho - Dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho Follow - New Rustacean: - Twitter: @newrustacean - App.net: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - Twitter: @chriskrycho - App.net: @chriskrycho 18:46 full
Bonus 2: Legacy Code https://newrustacean.com/show_notes/bonus/_2/ Legacy Code

Software developers spend a large part of our careers dealing with legacy code. But what is the best way to deal with legacy code? When should you rip out the old and rewrite it, and when should you opt for smaller clean-up jobs because, however ugly, what is already present works?

Sponsors

  • Chris Palmer
  • Derek Morr
  • Luca Schmid
  • Micael Bergeron
  • Ralph Giles (“rillian”)
  • reddraggone9
  • William Roe

Become a sponsor

Follow

]]>
Sun, 06 Dec 2015 11:23:54 -0700 7FB6C998-E813-4E17-8EFB-CD29135DCD2D Chris Krycho Paying off technical debt, refactoring, and cleaning up old code. Software developers spend a large part of our careers dealing with legacy code. But what is the _best_ way to deal with legacy code? When should you rip out the old and rewrite it, and when should you opt for smaller clean-up jobs because, however ugly, what is already present _works_? SPONSORS - Chris Palmer - Derek Morr - Luca Schmid - Micael Bergeron - Ralph Giles (“rillian”) - reddraggone9 - William Roe Become a sponsor - Patreon.com/newrustacean - Venmo.com/chriskrycho - Dwolla.com/hub/chriskrycho - Cash.me/$chriskrycho FOLLOW - New Rustacean: - Twitter: @newrustacean - App.net: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - Twitter: @chriskrycho - App.net: @chriskrycho 9:41 full
Bonus 1: Polyglot Programming Promises and Perils https://newrustacean.com/show_notes/bonus/_1/ Polyglot Programming Promises and Perils

Sometimes, you’re doing a technical interview, and you just cannot figure out why your JavaScript function isn’t behaving like it should… and then, prompted by the interviewer, you realize that you’re not returning anything. Polyglot programming is beautiful, and wonderful, and sometimes it bites you when you aren’t looking.

Links

Sponsors

Become a sponsor

Follow

]]>
Wed, 25 Nov 2015 09:27:09 -0700 78C8C06F-DEB6-4821-9995-E550FBA87059 Chris Krycho The delights and challenges of knowing (or even just learning) lots of languages. 8:28 full
e006: Modularize this! https://newrustacean.com/show_notes/e006/ Notes

Today, we are talking about modules, packages, and APIs in Rust. Taking a bit of a breather after some pretty hard material the last few weeks.

For reference, the Rust book section on Crates and Modules will be very helpful.

Corrigenda

I accidentally called this episode 5, instead of episode 6. Whoops.

Just before the 15:00 mark, while discussing libraries, I referred to “e006.md” when I meant to say “e006.rs”. Slips of the tongue inspired by the fact that Rust (delightfully) uses Markdown for its documentation.

Links

Sponsors

Become a sponsor

Follow

]]>
Mon, 16 Nov 2015 08:36:26 -0700 6707AF5D-82F4-40D5-9DB5-7003D571EEB6 Chris Krycho Designing APIs, and using packages ("crates") and modules Designing APIs, and using packages (“crates”) and modules Notes Today, we are talking about modules, packages, and APIs in Rust. Taking a bit of a breather after some pretty hard material the last few weeks. For reference, the Rust book section on Crates and Modules will be very helpful. Corrigenda I accidentally called this episode 5, instead of episode 6. *Whoops.* Just before the 15:00 mark, while discussing libraries, I referred to “e006.md” when I meant to say “e006.rs”. Slips of the tongue inspired by the fact that Rust (delightfully) uses Markdown for its documentation. Sponsors - reddraggone9 - Chris Patti (Podcast.__init__) Become a sponsor - https://www.patreon.com/newrustacean - https://venmo.com/chriskrycho - dwolla.com/hub/chriskrycho - ttps://cash.me/$chriskrycho 18:22 full
e005: Allocate it where? https://newrustacean.com/show_notes/e005/ Allocate it where?

Subject: Returning functions from other functions, and thinking about the stack, the heap, and reference types.

  • MP3
  • Notes

    This episode, we look at returning functions from other functions, and as part of that discuss some basics about the stack and the heap—and why we need to care about them for returning functions.

    The functions themselves are not especially interesting; they just show you the basic form you use to return functions from other functions, and how to then use them in another function. You’ll want to take a detailed look instead at the documentation for each (or just read the source!), because that’s where the meat of the discussion in this week’s code is.

    Links

    Sponsors

    Become a sponsor

    Follow

    ]]>
    Sun, 08 Nov 2015 13:15:53 -0700 2BA666AD-2288-4599-AC61-7B545FD2C539 Chris Krycho Returning functions from other functions, and thinking about the stack, the heap, and reference types. Returning functions from other functions, and thinking about the stack, the heap, and reference types. NOTES This episode, we look at returning functions from other functions, and as part of that discuss some basics about the stack and the heap—and why we need to care about them for returning functions. The functions themselves are not especially interesting; they just show you the basic form you use to return functions from other functions, and how to then use them in another function. You’ll want to take a detailed look instead at the documentation for each (or just read the source!), because that’s where the meat of the discussion in this week’s code is. SPONSORS - reddraggone9 - Chris Patti Become a sponsor - Patreon.com/newrustacean - Venmo.com/chriskrycho - Dwolla.com/hub/chriskrycho - Cash.me FOLLOW - New Rustacean: - Twitter: @newrustacean - App.net: @newrustacean - Email: hello@newrustacean.com - Chris Krycho - Twitter: @chriskrycho - App.net: @chriskrycho 18:30 full
    e004: Functionalized https://newrustacean.com/show_notes/e004/ Date: October 29, 2015

    Subject: Functions, methods, closures, and function as arguments!

    Notes

    This week’s episode covers the basics of all sorts of functions: normal functions, methods, and closures.

    Closures

    Links

    Follow/Support

    ]]>
    Thu, 29 Oct 2015 20:45:12 -0600 BC4D9C42-0F4C-4497-9059-436A8906657E Chris Krycho Functions, methods, closures, and function as arguments! Functions, methods, closures, and function as arguments! NOTES This week’s episode covers the basics of all sorts of functions: normal functions, methods, and closures. Closures - An explanation (in Ruby) by Martin Fowler - Rust book - Rust by Example - “What is a closure?” (Progammers Stack Exchange) ‚Äì the first answer is the best, but the second answer may be a helpful stepping stone for people just getting their heads around this and coming from OOP languages like C++ or Java (even though I disagree with the explanation in some ways). - “What is a closure?” (Stack Overflow) – careful, thorough answer using JavaScript as an example. LINKS - Exercism (hat tip: Lechindanier on GitHub) - Rust Learning - Rust and Swift (viii) FOLLOW/SUPPORT - New Rustacean: - Twitter: @newrustacean - App.net: @newrustacean - Patreon.com/chriskrycho - Dwolla.com/hub/chriskrycho - Email: hello@newrustacean.com - Chris Krycho - Twitter: @chriskrycho - App.net: @chriskrycho 17:07 full
    e003: No. more. nulls. https://newrustacean.com/show_notes/e003/ No More Nulls

    Subject: Enumerated (enum) types, pattern matching, and meaningful return types.

    Notes

    Today’s episode discusses, in order:

    • Enumerated types, with an eye to the difference between structs and enums, and to the differences between enums in C and in Rust.
    • Pattern matching, with a focus on using them with enumerated types and some discussion about how they differ from switch blocks in C-like languages.
    • Using the Option and Result enumerated types with pattern matching to provide meaningful returns from functions safely.

    Order

    There is a specific order to the examples below, and it is not the automatically-alphabetized order rendered by rustdoc. Instead, you should work through in the sequence they appear in the source:

    1. RelatedishThings
    2. demonstrate_basic_enumeration
    3. demonstrate_match
    4. get_an_option
    5. demonstrate_option
    6. get_a_result
    7. demonstrate_result

    Follow/Support

    • New Rustacean:
      • Twitter: @newrustacean
      • App.net: @newrustacean
      • Patreon
      • Email:
    • Chris Krycho
    ]]>
    Wed, 21 Oct 2015 11:10:12 -0600 E39A4582-8095-4645-8925-AB2887828F93 Chris Krycho Enumerated (`enum`) types, pattern matching, and meaningful return values. No More Nulls - Date: October 21, 2015 - Subject: Enumerated (`enum`) types, pattern matching, and meaningful return values. # Notes Today’s episode discusses, in order: - Enumerated types, with an eye to the difference between structs and enums, and to the differences between enums in C and in Rust. - Pattern matching, with a focus on using them with enumerated types and some discussion about how they differ from switch blocks in C-like languages. - Using the Option and Result enumerated types with pattern matching to provide meaningful returns from functions safely. ## Order There is a specific order to the examples below, and it is _not_ the automatically-alphabetized order rendered by rustdoc. Instead, you should work through in the sequence they appear in the source: 1. RelatedishThings 2. demonstrate_basic_enumeration 3. demonstrate_match 4. get_an_option 5. demonstrate_option 6. get_a_result 7. demonstrate_result 16:51 full
    e002: Something borrowed, something… moved? https://newrustacean.com/show_notes/e002/ Something borrowed, something… moved?

    Subject: The struct data type constructor, and the basics of Rust’s “ownership” concept and “borrowing” and “moving”.

    Follow/Support

    Notes

    Today’s episode discusses, and the associated source code demonstrates, a few basic behaviors of structs… including borrowing!

    After taking a short look at one of Rust’s basic approaches to creating new types, we dive into a fairly thorough overview of how borrowing works in fairly run-of-the-mill Rust code. This is a basic introduction, and as such I’m not getting into things like heap-allocated memory (Box) or dealing with move semantics with threads or closures. (I haven’t actually figured those out well enough yet to write something like this for them!)

    As usual, you’ll want to have the src open to see what I’m doing with the components documented below.

    Links

    ]]>
    Sun, 11 Oct 2015 20:24:16 -0600 03DD0BB6-9615-420A-A43B-B6EB0BBCD1C4 Chris Krycho Borrow a `struct` for a while. Then give it back, or keep it for yourself! Something borrowed, something… moved? * Date: October 12, 2015 * Subject: The struct data type constructor, and the basics of Rust’s “ownership” concept and “borrowing” and “moving”. * Audio: * M4A * MP3 * Ogg Follow/Support * New Rustacean: * Twitter: @newrustacean * App.net: @newrustacean * Patreon * Email: hello@newrustacean.com * Chris Krycho * Twitter: @chriskrycho * App.net: @chriskrycho Notes Today’s episode discusses, and the associated source code demonstrates, a few basic behaviors of structs… including borrowing! After taking a short look at one of Rust’s basic approaches to creating new types, we dive into a fairly thorough overview of how borrowing works in fairly run-of-the-mill Rust code. This is a basic introduction, and as such I’m not getting into things like heap-allocated memory (Box) or dealing with move semantics with threads or closures. (I haven’t actually figured those out well enough yet to write something like this for them!) As usual, you’ll want to have the src open to see what I’m doing with the components documented below. Links * rustfmt – a tool for formatting Rust code * repo * “rustfmt-ing Rust` * Reddit discussion * RFC for incremental compilation * Text of the RFC * GitHub pull request 17:12 full
    e001: Document All the Things https://newrustacean.com/show_notes/e001/ Document all the things!

    Subject: Documentation in general, and rustdoc and cargo doc in particular.

    Follow/Support

    Notes

    This is a mostly-empty module, and it is intended as such. Why? Well, because almost all the sample code exists in these comments, which serve as the show notes. If you listen to the episode or take a look at the source files, you’ll see how it works!

    The components below are included solely so you can see how the docstrings work with each kind of thing. Make sure to click on the names of the items: there is more documentation there. Again, take a look at the source to see how it looks in the context of a file module.

    Note that this module-level docstring uses rather than `///`-style comments. This is because this docstring is documenting the item which contains it, rather than the following item. Per [Rust RFC 505][1], the preferred approach is always to use the "following" form (`///`) rather than the "containing" form (), except for module-level docs like these. (I will be following RFC 505 throughout.)

    Links

    ]]>
    Sat, 03 Oct 2015 14:04:28 -0600 9846F954-2459-4E89-BAF6-0DB4DA62E6D3 Chris Krycho Documentation in general, and rustdoc and cargo doc in particular. Documentation in general, and rustdoc and cargo doc in particular. Document all the things! * Date: October 3, 2015 * Subject: Documentation in general, and rustic and cargo doc in particular. * Audio: * M4A * MP3 Follow/Support * New Rustacean: * Twitter: @newrustacean * App.net: @newrustacean * Patreon * Email: hello@newrustacean.com * Chris Krycho * Twitter: @chriskrycho * App.net: @chriskrycho Notes This is a mostly-empty module, and it is intended as such. Why? Well, because almost all the sample code exists in these comments, which serve as the show notes. If you listen to the episode or take a look at the source files, you’ll see how it works! The components below are included solely so you can see how the docstrings work with each kind of thing. Make sure to click on the names of the items: there is more documentation there. Again, take a look at the source to see how it looks in the context of a file module. Note that this module-level docstring uses rather than `///`-style comments. This is because this docstring is documenting the item which contains it, rather than the following item. Per [Rust RFC 505][1], the preferred approach is always to use the &quot;following&quot; form (`///`) rather than the &quot;containing&quot; form (), except for module-level docs like these. (I will be following RFC 505 throughout.) Links * Rust and MSVC tracking issue * Other documentation tools: * Predecessors: * Python’s Sphinx tool * Oxygen * JSDoc * JavaDoc * Other new languages with Markdown tooling * Julia has a built-in documentation system * Elixir has ex_doc * Rust 1.3 release announcement * Rust’s package hosting: crates.io * Crater for testing for backwards compatibility * Semantic versioning * “Stability as a Deliverable”: Rust official blog post on version stability, backwards compatibility, and release channels. * The Rust book chapter on rustc 17:06 full
    e000: Hello, world! https://newrustacean.com/show_notes/e000/ Hello, World!

    Subject: The host, the language, and the show!

    Today’s show is pretty meta. You can skip it if you just want to start with something more technical, but I thought listeners might want to know a little about the origins of the show and my own background, so that’s what you get today. Next time, we’ll be tackling the rustdoc command in some detail.


    This is an almost-empty module: we aren’t doing any fun code samples yet. I included the standard “Hello, world!” example, because how could I not? However, at some point in the future, there will be much more detailed code samples available:

    Hopefully, the result will be a pretty helpful bunch of side content along with the audio of the podcast itself.

    ]]>
    Thu, 24 Sep 2015 17:14:50 -0600 CCE404BC-4B4A-4F28-A687-9BCC66C08CEF Chris Krycho A little about the host, and a little about the format of the show! Hello, world! * Date: September 24, 2015 * Subject: The host, the language, and the show! * Audio: * M4A * MP3 Today’s show is pretty meta. You can skip it if you just want to start with something more technical, but I thought listeners might want to know a little about the origins of the show and my own background, so that’s what you get today. Next time, we’ll be tackling the rustic command in some detail. This is an almost-empty module: we aren’t doing any fun code samples yet. I included the standard “Hello, world!” example, because how could I not? However, at some point in the future, there will be much more detailed code samples available: * in the GitHub repository for the show * in the show notes attached to each episode Hopefully, the result will be a pretty helpful bunch of side content along with the audio of the podcast itself. 17:11 full
    ================================================ FILE: resources/media-playback.css ================================================ .playback-rate-controls ul { margin: 0; padding: 0; list-style: none; text-align: center; } .playback-rate-controls li { display: inline; } .playback-rate-controls li:not(:last-of-type)::after { content: " | "; } ================================================ FILE: resources/media-playback.js ================================================ function setPlaybackSpeed(speed) { [].slice.call(document.querySelectorAll("audio,video")).map(function(e, idx) { e.playbackRate = speed; }); } (function() { [].slice.call(document.querySelectorAll("audio,video")).map(function(e, idx) { const controls = document.createElement("div"); controls.className = "playback-rate-controls"; const controlsList = document.createElement("ul"); const constrolsHTML = [0.5, 1, 1.25, 1.5, 1.75, 2] .map( s => `
  • ${s}⨉
  • ` ) .join("\n"); controlsList.innerHTML = constrolsHTML; controls.appendChild(controlsList); e.parentNode.insertBefore(controls, e.nextSibling); }); })(); ================================================ FILE: rust-toolchain.toml ================================================ [toolchain] channel = "nightly-2024-06-10" ================================================ FILE: src/bonus/_1.rs ================================================ //! Polyglot programming promises and perils //! //! - **Date:** November 25, 2015 //! - **Subject:** The delights and challenges of knowing (or even just //! learning) lots of languages. //! - [**Audio**](https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/1.mp3) //! //! //! //! //! Sometimes, you're doing a technical interview, and you just cannot figure //! out why your JavaScript function isn't behaving like it should... and then, //! prompted by the interviewer, you realize that you're not returning anything. //! Polyglot programming is beautiful, and wonderful, and sometimes it bites you //! when you aren't looking. //! //! # Links //! //! - [Scala][links-1] //! - [F♯][links-2] //! - [Elixir][links-3] //! //! [links-1]: http://www.scala-lang.org //! [links-2]: http://fsharp.org //! [links-3]: http://elixir-lang.org //! //! # Sponsors //! //! - reddraggone9 //! - [Chris Patti][sponsors-1] //! //! [sponsors-1]: http://podcastinit.com //! //! ## Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! # Follow //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) ================================================ FILE: src/bonus/_10.rs ================================================ //! "Becoming a Contributor" //! //! - **Date:** March 17, 2018 //! - **Subject:** My Rust Belt Rust 2017 talk! //! - [**Audio:**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/10.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! - [slides] //! - [video] //! - [script on my website] //! //! [slides]: http://www.chriskrycho.com/talks/rust-belt-rust/#/ //! [video]: https://www.youtube.com/watch?v=Abu2BNixXak //! [script on my website]: http://www.chriskrycho.com/2017/becoming-a-contributor.html //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/bonus/10-script.md")] pub struct Script; ================================================ FILE: src/bonus/_13.rs ================================================ //! I Still Make Silly Mistakes //! //! - **Date:** February 28, 2019 //! - **Subject:** A story about parsing command-line arguments manually and //! some thoughts on “rookie mistakes.” //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/13.mp3 //! [script]: https://newrustacean.com/show_notes/bonus/_13/struct.script //! //! //! //! Show Notes //! ---------- //! //! - [why you might want to invoke the same program with different names][an interesting discussion] //! - [Python’s argparse library] //! - [Commander in Node] //! - [clap] //! - [structopt] //! - [pulldown-cmark] //! //! [an interesting discussion]: https://unix.stackexchange.com/questions/315812/why-does-argv-include-the-program-name "Why does argv include the program name?" //! [Python’s argparse library]: https://docs.python.org/3.7/library/argparse.html#module-argparse //! [Commander in Node]: https://github.com/tj/commander.js //! [clap]: https://clap.rs //! [structopt]: https://github.com/TeXitoi/structopt //! [pulldown-cmark]: https://github.com/raphlinus/pulldown-cmark //! //! Sponsors //! -------- //! //! Thanks to Parity for sponsoring the show and hiring Rust developers! //! //! [parity]: https://www.parity.io/jobs //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Lozada //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - Arlen Haftevani //! - [Arlo (Hyena)] //! - [Behnam Esfahbod] //! - [Benjamin Manns] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Cat Dad //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Christoffer Ceutz //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Carroll //! - David Hewson //! - [Derek Morr] //! - Doug Reeves //! - [Douglas Correa] //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - Evan Stoll //! - [Fabio (decathorpe)] //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - Hoàng Đức Hiếu //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - [Jason Bowen] //! - [Jendrik Illner] //! - Jerome Froelich //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - Jonah //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Mou //! - Joseph Schrag //! - [Joe Percy] //! - Justin Ossevoort //! - Kai Yao //! - Kazutaka Mise //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Malnormalulo] //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - [Michael Melanson] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Soren Bramer Schmidt] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Zak van der Merwe //! - Zachary Snyder //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [Arlo (Hyena)]: https://asonix.dog/@asonix //! [Behnam Esfahbod]: https://github.com/behnam //! [Benjamin Manns]: https://www.benmanns.com/ //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Douglas Correa]: http://learnrust.io/ //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Evan Stoll]: https://github.com/evanjs //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jason Bowen]: https://twitter.com/jwbowen //! [Jendrik Illner]: https://www.jendrikillner.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [Joe Percy]: http://joetdc.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Malnormalulo]: https://twitter.com/Malnormalulo //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Michael Melanson]: https://www.michaelmelanson.net //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Soren Bramer Schmidt]: http://prisma.io/ //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/bonus/13-silly-mistakes.md")] pub struct Script; ================================================ FILE: src/bonus/_14.rs ================================================ //! How the Sausage Gets Made //! //! - **Date:** March 23, 2019 //! - **Subject:** How I make the show, and why you won’t find it on Google Play, Spotify, or Stitcher. //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/14.mp3 //! [script]: https://newrustacean.com/show_notes/bonus/_14/struct.script //! //! //! //! Show Notes //! ---------- //! //! - [Winning Slowly][ws] //! - guest lectures on podcasting: [A], [B] //! - Audio recording/editing/production software: //! - [Icecast] //! - [Rogue Amoeba] //! - [Audio Hijack] //! - [Loopback] //! - [Ferrite] //! - [iZotope RX] //! - previous episodes of interest //! - building a [markdown link extraactor] //! - [using rustdoc] //! //! [ws]: https://winningslowly.org //! [A]: https://winningslowly.org/bonus.03/ //! [B]: https://winningslowly.org/bonus.04/ //! [Icecast]: https://icecast.org //! [Audio Hijack]: https://www.rogueamoeba.com/audiohijack/ //! [Loopback]: https://www.rogueamoeba.com/loopback/ //! [Rogue Amoeba]: https://www.rogueamoeba.com/ //! [Ferrite]: https://www.wooji-juice.com/products/ferrite/ //! [iZotope RX]: https://www.izotope.com/en/products/repair-and-edit/rx.html //! [markdown link extractor]: https://github.com/chriskrycho/extract-md-links //! [using rustdoc]: https://newrustacean.com/show_notes/e001/ //! //! Sponsors //! -------- //! //! Thanks to Parity for sponsoring the show and hiring Rust developers! //! //! [parity]: https://www.parity.io/jobs //! //! ### Patreon Sponsors //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Lozada //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - Arlen Haftevani //! - [Arlo (Hyena)] //! - Arun Kulshreshtha //! - [Behnam Esfahbod] //! - [Benjamin Manns] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Cat Dad //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Christoffer Ceutz //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Carroll //! - David Hewson //! - [Derek Morr] //! - Doug Reeves //! - [Douglas Correa] //! - Edmund Kump //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - [Evan Stoll] //! - [Fabio (decathorpe)] //! - [Fabio Correa] //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - Hoàng Đức Hiếu //! - Hugo Josefson //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - [Jason Bowen] //! - [Jendrik Illner] //! - Jerome Froelich //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - Jonah //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Mou //! - Joseph Schrag //! - [Joe Percy] //! - Justin Ossevoort //! - Kai Yao //! - Kazutaka Mise //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Malnormalulo] //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - [Michael Melanson] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Oladapo Fadeyi //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Soren Bramer Schmidt] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Zak van der Merwe //! - Zachary Snyder //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [Arlo (Hyena)]: https://asonix.dog/@asonix //! [Behnam Esfahbod]: https://github.com/behnam //! [Benjamin Manns]: https://www.benmanns.com/ //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Douglas Correa]: http://learnrust.io/ //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Evan Stoll]: https://github.com/evanjs //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Fabio Correa]: https://linkedin.com/in/feamcor //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jason Bowen]: https://twitter.com/jwbowen //! [Jendrik Illner]: https://www.jendrikillner.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [Joe Percy]: http://joetdc.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Malnormalulo]: https://twitter.com/Malnormalulo //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Michael Melanson]: https://www.michaelmelanson.net //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Soren Bramer Schmidt]: http://prisma.io/ //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/bonus/14-my-workflow.md")] pub struct Script; ================================================ FILE: src/bonus/_2.rs ================================================ //! Legacy code //! //! - **Date:** December 6, 2015 //! - **Subject:** Paying off technical debt, refactoring, and cleaning up old code. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/2.mp3 //! //! //! //! Software developers spend a large part of our careers dealing with legacy //! code. But what is the *best* way to deal with legacy code? When should you //! rip out the old and rewrite it, and when should you opt for smaller clean-up //! jobs because, however ugly, what is already present *works*? //! //! # Sponsors //! //! - Chris Palmer //! - [Derek Morr][sponsors-2] //! - Luca Schmid //! - Micael Bergeron //! - Ralph Giles ("rillian") //! - reddraggone9 //! - [William Roe][sponsors-7] //! //! [sponsors-2]: https://twitter.com/derekmorr //! [sponsors-7]: http://willroe.me //! //! ## Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! # Follow //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) ================================================ FILE: src/bonus/_3.rs ================================================ //! Building as a community //! //! - **Date:** January 31, 2016 //! - **Subject:** The value of a good community, and how you can help Rust today. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/3.mp3 //! //! //! //! //! Notes //! ----- //! //! Community is one of the most important parts of a programming language //! community, or indeed *any* technical community. In this episode, I talk //! a bit about what happens when you don't have a good community, how Rust's //! community has done well so far, and then how to keep building a good //! community and how to build good things *as* a community. //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Chris Palmer //! - [Derek Morr][s3] //! - Hamza Sheikh //! - Luca Schmid //! - Micael Bergeron //! - Ralph Giles ("rillian") //! - reddraggone9 //! - [William Roe][s9] //! //! [s3]: https://twitter.com/derekmorr //! [s9]: http://willroe.me //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! //! Follow //! ------ //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) ================================================ FILE: src/bonus/_4.rs ================================================ //! We *can* have nice things //! //! - **Date:** April 19, 2016 //! - **Subject:** Just how good Rust is, and how you can learn it even if you're busy //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/4.mp3 //! //! //! //! //! Notes //! ----- //! //! Sometimes life goes crazy and I don't have time to do all the technical //! writing required for a full episode, but I can't get Rust off my mind, so //! I record an episode like this one. Where I talk a bit about how versatile //! Rust is and suggest some surprising ways you might be able to use it. //! //! //! Links //! ----- //! //! - [Rust 1.8] blog post //! - [Fake] build tool in F♯ //! - [HackerNews] on Rust 1.8 //! + [Someone using it for personal projects][personal] //! + [Using it in place of scripting languages][scripting] //! - ["Feels like Python, runs like C"][python] //! //! //! [Rust 1.8]: http://blog.rust-lang.org/2016/04/14/Rust-1.8.html //! [Fake]: http://fsharp.github.io/FAKE/ //! [HackerNews]: https://news.ycombinator.com/item?id=11498426 //! [personal]: https://news.ycombinator.com/item?id=11498608 //! [scripting]: https://news.ycombinator.com/item?id=11499747 //! [python]: https://twitter.com/jdub/status/720801192884867073 //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - [Chris Palmer] //! - [Derek Morr] //! - Hamza Sheikh //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - [Pascal Hertleif] //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - reddraggone9 //! - Ryan Ollos //! - Vesa Kaihlavirta //! - [William Roe] //! //! [Chris Palmer]: http://red-oxide.org/ //! [Derek Morr]: https://twitter.com/derekmorr //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/bonus/_5.rs ================================================ //! Better than open source contributions //! //! - **Date:** May 9, 2016 //! - **Subject:** Some things matter more than contributing to open-source //! software in your free time. A *lot* more. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/5.mp3 //! //! //! //! //! Notes //! ----- //! //! It's trendy to ask for open-source work as evidence of your interest in tech //! and commitment to software development. Trendy and *completely wrong*. //! Companies should not demand open-source contributions from their employees, //! and beyond that, should learn to recognize that *profit* is not the most //! valuable thing in the world. People are. //! //! //! Links //! ----- //! //! - [Xi editor] //! - [Rust survey] //! - Expecting people to do open-source work //! + [Python Testing 18: Testing in Startups and Hiring Software //! Engineers with Joe Stump][podcast] //! + [Tweet about it by Joe Stump][tweet] //! //! [Xi editor]: https://github.com/google/xi-editor //! [Rust survey]: http://blog.rust-lang.org/2016/05/09/survey.html //! [podcast]: http://pythontesting.net/podcast/testing-in-startups-joe-stump-sprintly //! [tweet]: https://twitter.com/joestump/status/723635220256190464 //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - [Chris Palmer] //! - [Daniel Collin] //! - [Derek Morr] //! - Hamza Sheikh //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - [Pascal Hertleif] //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - reddraggone9 //! - Ryan Ollos //! - Vesa Kaihlavirta //! - [William Roe] //! //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/bonus/_6.rs ================================================ //! It doesn't have to be sexy //! //! - **Date:** August 20, 2016 //! - **Subject:** Building (and celebrating) all the little, not-so-glorious //! pieces of the Rust ecosystem. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/6.mp3 //! //! //! //! //! Notes //! ----- //! //! We love the Rust compiler team. But there's more to the Rust community, and //! more required for Rust to be as great as it can be, than just the language //! itself. We need to celebrate other libraries, and even the small ones, just //! as much (and maybe more) than changes to the language. We need to dig in and //! work on building the *whole* ecosystem. (The good news is, we are!) //! //! //! Links //! ----- //! //! - [`futures-rs`] //! + ["Zero-cost futures in Rust"][futures-blog] //! - [Tokio] //! + ["Announcing Tokio"][tokio-medium] (Carl Lerche on Medium) //! - [ShaderCat]: Graphics Programming with Unity and Rust //! - ["What's new with 'The Rust Programming Language'?"][trpl] //! - [Friends of Rust] //! - [`ring`]: Safe, fast, small crypto using Rust //! - [`alexa-rs`]: Rust library for building Alexa skills //! - [`gilrs`]: Game Input Library for Rust //! //! [`futures-rs`]: https://github.com/alexcrichton/futures-rs //! [futures-blog]: http://aturon.github.io/blog/2016/08/11/futures/ //! [Tokio]: https://github.com/tokio-rs/tokio //! [tokio-medium]: https://medium.com/@carllerche/announcing-tokio-df6bb4ddb34#.c9pqf9wyx //! [Friends of Rust]: https://www.rust-lang.org/en-US/friends.html //! [trpl]: http://words.steveklabnik.com/whats-new-with-the-rust-programming-language //! [`ring`]: https://github.com/briansmith/ring //! [`alexa-rs`]: https://github.com/neil-lobracco/alexa-rs //! [`gilrs`]: https://gitlab.com/Arvamer/gilrs //! [ShaderCat]: http://www.shadercat.com //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Cameron Mochrie //! - Cass Costello //! - [Chris Palmer] //! - [Daniel Collin] //! - [Derek Morr] //! - Doug Reeves //! - Eric Fulmer //! - Hamza Sheikh //! - [Jakub "Limeth" Hlusička] //! - [Jared Smith] //! - Keith Gray //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - [Pascal Hertleif] //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - Raph Levien //! - reddraggone9 //! - Ryan Ollos //! - Steven Murawski //! - Vesa Kaihlavirta //! - [William Roe] //! //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jared Smith]: http://twitter.com/jaredthecoder //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/bonus/_7.rs ================================================ //! Katas---or: learning by doing //! //! - **Date:** September 10, 2016 //! - **Subject:** Building (and celebrating) all the little, not-so-glorious //! pieces of the Rust ecosystem. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/7.mp3 //! //! //! //! //! Notes //! ----- //! //! One of the best ways to learn is to pick a small problem you have already //! internalized, and to do it again but in a new language or in a new way in a //! language you already know. //! //! //! Links //! ----- //! //! - [AreWeGameYet] //! - [AreWeIDEYet] //! - [AreWeWebYet] //! - [Setting our vision for the 2017 cycle][vision] //! - [Incremental Compilation] //! - `cargo-incremental`: //! + [internals post] //! + [repo] //! - [Elm] //! - Dave Thomas' [CodeKata] //! - Crates I used in my Rust "kata": //! + Hyper //! * [docs][hyper-docs] //! * [crate][hyper-crate] //! * [repo][hyper-repo] //! + Serde //! * [docs][serde-docs] //! * [crate][serde-crate] //! * [repo][serde-repo] //! + Pencil (inspired by [Flask]) //! * [docs][pencil-docs] //! * [crate][pencil-crate] //! * [repo][pencil-repo] //! + `handlebars-rust`: //! * [docs][handlebars-docs] //! * [crate][handlebars-crate] //! * [repo][handlebars-repo] //! //! [AreWeGameYet]: http://arewegameyet.com //! [AreWeIDEYet]: https://areweideyet.com //! [AreWeWebYet]: http://www.arewewebyet.org //! [vision]: https://internals.rust-lang.org/t/setting-our-vision-for-the-2017-cycle/3958 //! [Incremental Compilation]: https://blog.rust-lang.org/2016/09/08/incremental.html //! [internals post]: https://internals.rust-lang.org/t/want-to-help-develop-tool-for-testing-incremental-compilation/3963 //! [repo]: https://github.com/nikomatsakis/cargo-incremental/ //! [Elm]: http://elm-lang.org //! [CodeKata]: http://codekata.com //! [hyper-docs]: https://docs.rs/hyper/ //! [hyper-crate]: https://crates.io/crates/hyper //! [hyper-repo]: https://github.com/hyperium/hyper //! [serde-docs]: https://docs.rs/serde/ //! [serde-crate]: https://crates.io/crates/serde //! [serde-repo]: https://github.com/serde-rs/serde //! [Flask]: http://flask.pocoo.org //! [pencil-docs]: https://docs.rs/pencil/ //! [pencil-crate]: https://crates.io/crates/pencil //! [pencil-repo]: https://github.com/fengsp/pencil //! [handlebars-docs]: https://docs.rs/handlebars/ //! [handlebars-crate]: https://crates.io/crates/handlebars //! [handlebars-repo]: https://github.com/sunng87/handlebars-rust //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Cameron Mochrie //! - [Chris Palmer] //! - [Daniel Collin] //! - [Derek Morr] //! - Doug Reeves //! - Hamza Sheikh //! - [Jakub "Limeth" Hlusička] //! - [Jupp Müller] //! - Keith Gray //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Matthew Piziak //! - Micael Bergeron //! - Nils Tekampe //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - Raph Levien //! - reddraggone9 //! - Ryan Ollos //! - Sean Jensen-Gray //! - Steven Murawski //! - Vesa Kaihlavirta //! - [William Roe] //! //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/bonus/_8.rs ================================================ //! Giving back (by teaching) //! //! - **Date:** March 19, 2017 //! - **Subject:** On the responsibilities and opportunities we have to help //! others with our knowledge and abilities. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/8.mp3 //! //! //! //! //! Notes //! ----- //! //! Many of us have been very blessed with opportunities and support as we learn //! software. We should go out of our way to share with others in kind. Today, //! my focus is on teaching, but there are lots of ways to "give back." And I'd //! love to hear *your* thoughts and things *you're* doing in that vein! //! //! //! Links //! ----- //! //! - [Julia Evans][jvns] //! - [`keyof` and Mapped Types in TypeScript 2.1][ts-post] -- the blog post I //! mentioned writing a few months ago. //! //! [jvns]: http://jvns.ca //! [ts-post]: http://www.chriskrycho.com/2016/keyof-and-mapped-types-in-typescript-21.html //! //! //! Sponsors //! -------- //! //! //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - Ben Whitley //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Christopher Giffard] //! - Dan Abrams //! - [Daniel Collin] //! - [Derek Morr] //! - Eugene Bulkin //! - [Jakub "Limeth" Hlusička] //! - Jordan Henderson //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Lachlan Collins //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Raph Levien //! - reddraggone9 //! - Steven Murawski //! - [Stuart Hinson] //! - Tyler Harper //! - Vesa Kaihlavirta //! - Vlad Bezden //! - Warren Harper //! - [William Roe] //! - Zaki //! //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/bonus/_9.rs ================================================ //! Open source is mostly just normal people //! //! - **Date:** August 14, 2017 //! - **Subject:** My experience with ember-cli-typescript as an example: //! we're all just people muddling along and doing our best. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/9.mp3 //! //! //! //! //! Links and Notes //! --------------- //! //! - [ember-cli-typescript] //! - [The Bike Shed #118: Nonsense In, Nonsense Out][bike shed] //! - Sean's appearance on New Rustacean: [Interview 1] //! //! [ember-cli-typescript]: https://github.com/typed-ember/ember-cli-typescript //! [bike shed]: http://bikeshed.fm/118 //! [Interview 1]: https://www.newrustacean.com/show_notes/interview/_1/index.html //! //! //! Sponsors //! -------- //! //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Christopher Giffard] //! - Dan Abrams //! - [Daniel Collin] //! - [David W. Allen] //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jonathan Turner //! - Jordan Henderson //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - Oliver Uvman - see the [Tomaka Patreon] and [arewegameyet.com] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - Raphael //! - [Rob Tsuk] //! - reddraggone9 //! - [Sebastián Ramírez Magrí] //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Warren Harper //! - [William Roe] //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Rob Tsuk]: https://github.com/rtsuk //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [Tomaka Patreon]: https://www.patreon.com/tomaka/ //! [arewegameyet.com]: http://arewegameyet.com/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/bonus/burnout.rs ================================================ //! Burnout //! //! - **Date:** September 22, 2018 //! - **Subject:** What burnout is, the many ways it can happen to us, and //! what we can do about it. //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/burnout.mp3 //! [script]: https://newrustacean.com/show_notes/bonus/burnout/struct.script //! //! //! //! Show Notes //! ---------- //! //! - [My blog posts on burnout][blog] (and [the RSS feed][rss]) //! - [Mayo clinic guidelines][mayo] //! //! [blog]: https://www.chriskrycho.com/burnout //! [rss]: http://www.chriskrycho.com/feeds/burnout.xml //! [mayo]: https://www.mayoclinic.org/healthy-lifestyle/adult-health/in-depth/burnout/art-20046642 //! //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Antonin Carette //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Brian Casiello //! - Brian Manning //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Damien Stanton] //! - Dan Abrams //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - [Daniel P. Clark] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - [Graham Wihlidal] //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - James Cooper //! - Jerome Froelich //! - [Joar Wandborg] //! - [John Rudnick] //! - Jon //! - Jonathan Turner //! - Joseph Hain //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Laurie Hedge //! - Luca Schmid //! - Lukas Eller //! - [Luiz Irber] //! - Mark LeMoine //! - [Martin Heuschober]: //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Connell] //! - [Nathan Sculli] //! - [Nick Coish] //! - [Nick Stevens] //! - [Nicolas Pochet] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Raj Venkalil //! - [Ramon Buckley] //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - Richard Dallaway //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - [Simon Dickson] //! - Simon G. //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Timm Preetz //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Graham Wihlidal]: https://wihlidal.com/ //! [Hans Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Joar Wandborg]: http://github.com/joar //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Luiz Irber]: http://luizirber.org/ //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Connell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckley]: http://www.inosion.com //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/bonus/burnout-script.md")] pub struct Script; ================================================ FILE: src/bonus/mod.rs ================================================ //! Bonus episodes: shorter, and usually more about community or philosophy. pub mod _1; pub mod _10; pub mod _13; pub mod _14; pub mod _2; pub mod _3; pub mod _4; pub mod _5; pub mod _6; pub mod _7; pub mod _8; pub mod _9; pub mod burnout; pub mod translating_between_languages; ================================================ FILE: src/bonus/translating_between_languages.rs ================================================ //! Translating Between Languages //! //! - **Date:** October 23, 2018 //! - **Subject:** Musings inspired by a project translating TypeScript to Rust //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/bonus/translating_between_languages.mp3 //! [script]: https://newrustacean.com/show_notes/bonus/translating_between_languages/struct.script //! //! //! //! //! Sponsors //! -------- //! //! Thanks to Manning for sponsoring the show *and* giving all of you a 40%-off //! discount on their whole store (but especially Carol Nichols' and Jake //! Goulding's _Rust in Motion_ video content and the _Rust in Action_ MEAP!) at //! [deals.manning.com/new-rustacean][manning] //! //! [manning]: http://bit.ly/2OXnlEb //! //! ### Patreon Sponsors //! //! - Aaron Turon //! - Adam Green //! - Aleksey Pirogov //! - Alexander Payne //! - Alexander Kryvomaz //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Bryan Stitt] //! - Bryce Johnston //! - Caryn Finkelman //! - Cass Costello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Daniel //! - Dan Abrams //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Hewson //! - [Derek Morr] //! - Doug Reeves //! - Eugene Bulkin //! - Fábio Botelho //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - "Jake ""ferris"" Taylor" //! - James Cooper //! - James Hagans II //! - Jerome Froelich //! - [Joar Wandborg] //! - [John Rudnick] //! - Jon //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Marhee //! - Justin Ossevoort //! - Kai Yao //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Tillemans //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Zak van der Merwe //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Joar Wandborg]: http://github.com/joar //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/bonus/translating-between-languages-script.md")] pub struct Script; ================================================ FILE: src/cysk/_1.rs ================================================ //! quick-xml //! //! - **Date:** January 8, 2017 //! - **Subject:** A pull-parser for reading and writing XML. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/cysk/1.mp3 //! //! //! //! Links //! ----- //! //! - [crates.io] //! - [docs.rs] //! - [GitHub] //! - [syntax highlighting] -- example from [lightning-rs] //! //! [crates.io]: https://crates.io/crates/quick-xml //! [docs.rs]: https://docs.rs/quick-xml/0.4.2/quick_xml/ //! [GitHub]: https://github.com/tafia/quick-xml //! [syntax highlighting]: https://github.com/chriskrycho/lightning-rs/blob/a1fcd0af2435c5f2fd4d7c4ef3a5a88f89bdd9f5/src/syntax_highlighting.rs //! [lightning-rs]: https://github.com/chriskrycho/lightning-rs //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Ben Whitley //! - Cameron Mochrie //! - [Chris Palmer] //! - [Christopher Giffard] //! - [Daniel Collin] //! - [Derek Morr] //! - [Jakub "Limeth" Hlusička] //! - Jordan Henderson //! - [Jupp Müller] //! - Keith Gray //! - Lachlan Collins //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Raph Levien //! - reddraggone9 //! - Ryan Ollos //! - Steven Murawski //! - Vesa Kaihlavirta //! - Vlad Bezden //! - [William Roe] //! - Zaki //! //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Philipp Keller]: https://twitter.com/hansapla //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/cysk/_2.rs ================================================ //! clap //! //! - **Date:** Feburary 14, 2017 //! - **Subject:** A Command-Line Argument Parser. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/cysk_2.mp3 //! //! //! //! Links //! ----- //! //! - [crates.io] //! - [docs.rs] //! - [GitHub] //! - [videos] //! - [book] //! - YAML: //! + example from clap //! * [YAML][clap-yaml] //! * [associated Rust implementation][clap-rs] //! + example from [lightning-rs]: //! * [YAML][lx-yaml] //! * [associated Rust implementation][lx-rs] //! //! [crates.io]: https://crates.io/crates/clap //! [docs.rs]: https://docs.rs/clap/2.20.3/clap/ //! [GitHub]: https://github.com/kbknapp/clap-rs //! [videos]: https://www.youtube.com/playlist?list=PLza5oFLQGTl2Z5T8g1pRkIynR3E0_pc7U //! [book]: https://book.clap.rs //! [clap-yaml]: https://github.com/kbknapp/clap-rs/blob/master/examples/17_yaml.yml //! [clap-rs]: https://github.com/kbknapp/clap-rs/blob/master/examples/17_yaml.rs //! [lx-yaml]: https://github.com/chriskrycho/lightning-rs/blob/a1fcd0af2435c5f2fd4d7c4ef3a5a88f89bdd9f5/src/cli.yml //! [lx-rs]: https://github.com/chriskrycho/lightning-rs/blob/a1fcd0af2435c5f2fd4d7c4ef3a5a88f89bdd9f5/src/cli.rs //! [lightning-rs]: https://github.com/chriskrycho/lightning-rs //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - Ben Whitley //! - [Charlie Egan] //! - [Chris Palmer] //! - [Christopher Giffard] //! - [Daniel Collin] //! - [Derek Morr] //! - [Jakub "Limeth" Hlusička] //! - Jordan Henderson //! - [Jupp Müller] //! - Keith Gray //! - Lachlan Collins //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Raph Levien //! - reddraggone9 //! - Steven Murawski //! - [Stuart Hinson] //! - Tyler Harper //! - Vesa Kaihlavirta //! - Vlad Bezden //! - [William Roe] //! - Zaki //! //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Philipp Keller]: https://twitter.com/hansapla //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/cysk/_3.rs ================================================ //! Rust Language Service //! //! - **Date:** April 18, 2017 //! - **Subject:** Where the RLS came from, what it can do, and how you can //! start using it today! //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/cysk_3.mp3 //! //! //! //! //! Notes //! ----- //! //! One major ergonomic improvement to developing in Rust in 2017 is coming via //! the *Rust Language Service*: an initiative that lets us share a common core //! of functionality between every editor – from Vim to VS Code and everything //! in between. In today's episode, I give some background on it and talk about //! how you can start using it today! //! //! //! Links //! ----- //! //! - Rust Language Service //! + [repo] //! + blog posts //! - [announcement] //! - [alpha 2 release] //! - [first `rustup` release] //! + [vscode-rust] //! - Language Server Protocol //! + [repo][lsp-repo] //! + [VS Code blog post] //! + [implementations] //! //! [repo]: https://github.com/rust-lang-nursery/rls //! [announcement]: http://www.jonathanturner.org/2017/01/rls-alpha-release.html //! [alpha 2 release]: http://www.jonathanturner.org/2017/03/rls-alpha-2.html //! [first `rustup` release]: http://www.jonathanturner.org/2017/04/rls-now-in-nightly.md.html //! [lsp-repo]: https://github.com/Microsoft/language-server-protocol //! [VS Code blog post]: https://code.visualstudio.com/blogs/2016/06/27/common-language-protocol //! [implementations]: https://github.com/Microsoft/language-server-protocol/wiki/Protocol-Implementations //! [vscode-rust]: https://github.com/editor-rs/vscode-rust //! //! Sponsors //! -------- //! //! - [Anthony Deschamps] //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - Ben Whitley //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Christopher Giffard] //! - Dan Abrams //! - [Daniel Collin] //! - [Derek Morr] //! - Eugene Bulkin //! - [Jakub "Limeth" Hlusička] //! - Jordan Henderson //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Lachlan Collins //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Raph Levien //! - reddraggone9 //! - Steven Murawski //! - [Stuart Hinson] //! - Tyler Harper //! - Vesa Kaihlavirta //! - Warren Harper //! - [William Roe] //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/cysk/bindgen_cbindgen.rs ================================================ //! bindgen and cbindgen //! //! - **Date:** May 17, 2019 //! - **Subject:** Automatic generation of FFI types between Rust and C APIs. //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/cysk/bindgen_cbindgen.mp3 //! [script]: https://newrustacean.com/show_notes/cysk/bindgen_cbindgen/struct.script //! //! //! //! Show Notes //! ---------- //! //! - bindgen //! - [the official guide] //! - [API docs] //! - [cbindgen] //! - [a blog post by one of the main authors of the crate] //! - [rust-ffi] //! - Binding libraries for scripting languages //! - [PyO3] //! - [Neon] //! - [Rustler] //! - [a great write-up from the folks at Discord] //! - [Helix] //! //! [a blog post by one of the main authors of the crate]: https://blog.eqrion.net/future-directions-for-cbindgen/ //! [the official guide]: https://rust-lang.github.io/rust-bindgen/ //! [API docs]: https://docs.rs/bindgen //! [cbindgen]: https://github.com/eqrion/cbindgen/ //! [rust-ffi]: https://github.com/eqrion/rust-ffi //! [PyO3]: https://github.com/PyO3/PyO3 //! [Rustler]: https://github.com/rusterlium/rustler //! [a great write-up from the folks at Discord]: https://blog.discordapp.com/using-rust-to-scale-elixir-for-11-million-concurrent-users-c6f19fc029d3 //! [Neon]: https://neon-bindings.com //! [Helix]: https://github.com/tildeio/helix //! //! Sponsors //! -------- //! //! Thanks to Parity for sponsoring the show and hiring Rust developers! //! //! [parity]: https://www.parity.io/jobs //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Lozada //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - Arlen Haftevani //! - [Arlo (Hyena)] //! - Arun Kulshreshtha //! - [Behnam Esfahbod] //! - [Benjamin Manns] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Cat Dad //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Christoffer Ceutz //! - Cristian Paul //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Carroll //! - David Hewson //! - [Derek Morr] //! - Dominic Cooney //! - Doug Reeves //! - [Douglas Correa] //! - Edmund Kump //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - [Evan Stoll] //! - [Fabio (decathorpe)] //! - [Fabio Correa] //! - Freeman P. Pascal //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - Hoàng Đức Hiếu //! - [Hugo Josefson] //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - [Jason Bowen] //! - [Jeff May] //! - [Jendrik Illner] //! - Jerome Froelich //! - JockeTF //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - Jonah //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Mou //! - Joseph Schrag //! - [Joe Percy] //! - Justin Ossevoort //! - Kai Yao //! - Kazutaka Mise //! - Keith Gray //! - Kilian Rault //! - Kyle //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Malnormalulo] //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - [Michael Melanson] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Oladapo Fadeyi //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - Romain Chossart //! - [Ryan Blecher] //! - [Ryan Osial] //! - Satoshi Yoshikawa //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Soren Bramer Schmidt] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Sven Huster //! - Tim Brooks //! - Tim Small //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - Zak van der Merwe //! - Zachary Snyder //! - [Zach Peters] //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [Arlo (Hyena)]: https://asonix.dog/@asonix //! [Behnam Esfahbod]: https://github.com/behnam //! [Benjamin Manns]: https://www.benmanns.com/ //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Douglas Correa]: http://learnrust.io/ //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Evan Stoll]: https://github.com/evanjs //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Fabio Correa]: https://linkedin.com/in/feamcor //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Hugo Josefson]: https://www.hugojosefson.com //! [Jason Bowen]: https://twitter.com/jwbowen //! [Jeff May]: https://gitlab.com/jeffmay //! [Jendrik Illner]: https://www.jendrikillner.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [Joe Percy]: http://joetdc.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Malnormalulo]: https://twitter.com/Malnormalulo //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Michael Melanson]: https://www.michaelmelanson.net //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Soren Bramer Schmidt]: http://prisma.io/ //! [Stuart Hinson]: http://stuarth.github.io/ //! [Zach Peters]: https://github.com/zpeters //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/cysk/bindgen-cbindgen-script.md")] pub struct Script; ================================================ FILE: src/cysk/mod.rs ================================================ //! Brief discussions of important and useful crates around the Rust ecosystem. pub mod _1; pub mod _2; pub mod _3; pub mod rayon; pub mod rocket; pub mod serde; pub mod wasm; pub mod bindgen_cbindgen; ================================================ FILE: src/cysk/rayon.rs ================================================ //! Rayon //! //! - **Date:** September 16, 2017 //! - **Subject:** Safe, threaded, parallel code in Rust! //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/cysk/rayon.mp3 //! //! //! //! //! Links and Notes //! --------------- //! //! ### Rayon //! //! - [Source] //! - [Crate] //! - [Docs] //! - [README] //! - [blog post] //! //! [Source]: https://github.com/nikomatsakis/rayon //! [Crate]: https://crates.io/crates/rayon //! [Docs]: https://docs.rs/rayon/ //! [README]: https://github.com/nikomatsakis/rayon/blob/master/README.md //! [blog post]: http://smallcultfollowing.com/babysteps/blog/2015/12/18/rayon-data-parallelism-in-rust/ //! //! ### Other things referenced on the show //! //! - [Request for Explanation #10] //! - [e016: `RefCell`s and code smells][e016] – on mutability //! - ["embarassingly parallel"] //! //! [Request for Explanation #10]: https://request-for-explanation.github.io/podcast/ep10-two-paths-diverged-in-a-yellow-wood/index.html //! [e016]: https://www.newrustacean.com/show_notes/e016/index.html //! ["embarassingly parallel"]: https://en.wikipedia.org/wiki/Embarrassingly_parallel //! //! Sponsors //! -------- //! //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - Dan Abrams //! - [Daniel Collin] //! - [David W. Allen] //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Piziak //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Sebastián Ramírez Magrí] //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Warren Harper //! - [William Roe] //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: https://twitter.com/daniel_collin //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/cysk/rocket.rs ================================================ //! Rocket //! //! - **Date:** June 30, 2017 //! - **Subject:** An accessible, well-designed web framework in Rust! //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/cysk/rocket.mp3 //! //! //! //! //! Links and Notes //! --------------- //! //! - [Rocket] //! - [Hyper] //! - [Iron] //! - [Django] //! - [Rails] //! - [ASP.NET MVC] //! - Procedural macros //! + in the Rust book //! * [first edition] //! * second edition – still in progress at time of publication //! + [RFC #1566] //! * [implementation tracking issue] //! - [metaprogramming] //! - [Lisp] //! //! [Rocket]: https://rocket.rs //! [Hyper]: https://hyper.rs //! [Iron]: http://ironframework.io //! [Django]: https://www.djangoproject.com //! [Rails]: http://rubyonrails.org //! [ASP.NET MVC]: https://www.asp.net/mvc //! [first edition]: https://doc.rust-lang.org/book/first-edition/procedural-macros.html //! [RFC #1566]: https://github.com/rust-lang/rfcs/pull/1566 //! [implementation tracking issue]: https://github.com/rust-lang/rust/issues/38356 //! [metaprogramming]: https://en.wikipedia.org/wiki/Metaprogramming //! [Lisp]: https://en.wikipedia.org/wiki/Lisp_(programming_language) //! //! //! Sponsors //! -------- //! //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Ben Whitley //! - Benjamin Wasty //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Christopher Giffard] //! - Dan Abrams //! - [Daniel Collin] //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Jakub "Limeth" Hlusička] //! - Jonathan Turner //! - Jordan Henderson //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Lachlan Collins //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Warren Harper //! - [William Roe] //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/cysk/serde.rs ================================================ //! Serde //! //! - **Date:** February 10, 2018 //! - **Subject:** The library for serialization and deserialization in Rust. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/cysk/serde.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! - [Serde] //! - [custom derive] //! - [`serde_json`] //! - [its JSON parsing][parse] //! - [its JSON writer][write] //! //! [Serde]: https://serde.rs //! [custom derive]: https://doc.rust-lang.org/book/first-edition/procedural-macros.html //! [`serde_json`]: https://github.com/serde-rs/json //! [parse]: https://github.com/serde-rs/json/blob/master/src/de.rs#L110 //! [write]: https://github.com/serde-rs/json/blob/master/src/ser.rs#L72 //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/cysk/serde.md")] pub struct Script; ================================================ FILE: src/cysk/wasm.rs ================================================ //! The wasm tools //! //! - **Date:** March 31, 2018 //! - **Subject:** wasm intro, `wasm-bindgen`, and `wasm-pack` //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/cysk/wasm.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! - [WebAssembly] //! - [asm.js] //! - [wasm-bindgen] //! - [wasm-pack] //! - Rust wasm working group //! - [GitHub org] //! - [Twitter] //! - [This week in Rust and WebAssembly][TWIRW] //! //! [WebAssembly]: https://webassembly.org //! [asm.js]: http://asmjs.org //! [wasm-bindgen]: https://github.com/rustwasm/wasm-bindgen //! [wasm-pack]: https://github.com/ashleygwilliams/wasm-pack //! [GitHub org]: https://github.com/rust-lang-nursery/rust-wasm //! [Twitter]: https://twitter.com/rustwasm //! [TWIRW]: https://rustwasm.github.io //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/cysk/serde.md")] pub struct Script; ================================================ FILE: src/e000.rs ================================================ //! Hello, world! //! //! - **Date:** September 24, 2015 //! - **Subject:** The host, the language, and the show! //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e000.mp3 //! //! //! //! Today's show is pretty meta. You can skip it if you just want to start with //! something more technical, but I thought listeners might want to know a //! little about the origins of the show and my own background, so that's what //! you get today. Next time, we'll be tackling the `rustdoc` command in some //! detail. //! //! --- //! //! This is an almost-empty module: we aren't doing any fun code samples yet. //! I included the standard "Hello, world!" example, because how could I not? //! However, at some point in the future, there will be much more detailed code //! samples available: //! //! - in the [GitHub repository] for the show //! - in the show notes attached to each episode //! //! [GitHub repository]: //github.com/chriskrycho/newrustacean.com //! //! Hopefully, the result will be a pretty helpful bunch of side content along //! with the audio of the podcast itself. //! //! # Follow/Support //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Patreon //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) /// Prints "Hello, world!" if you import it somewhere and run it. pub fn hello_world() { println!("Hello, world!"); } ================================================ FILE: src/e001.rs ================================================ //! Document all the things! //! //! - **Date:** October 3, 2015 //! - **Subject:** Documentation in general, and `rustdoc` and `cargo doc` in //! particular. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e001.mp3 //! //! //! //! # Notes //! This is a mostly-empty module, and it is intended as such. Why? Well, //! because *almost* all the sample code exists in these comments, which serve //! as the show notes. If you listen to the episode or take a look at the //! [source files][src], you'll see how it works! //! //! [src]: /src/show_notes/e001.rs.html //! //! The components below are included *solely* so you can see how the //! docstrings work with each kind of thing. Make sure to click on the names of //! the items: there is more documentation there. Again, take a look at the //! [source][src] to see how it looks in the context of a file module. //! //! Note that this module-level docstring uses `//!` rather than `///`-style //! comments. This is because this docstring is documenting the item which //! contains it, rather than the following item. Per [Rust RFC 505][1], the //! preferred approach is always to use the "following" form (`///`) rather than //! the "containing" form (`//!`), except for module-level docs like these. //! (I will be following RFC 505 throughout.) //! //! [1]: https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md //! //! # Links //! - [Rust and MSVC tracking issue][2] //! - Other documentation tools: //! + Predecessors: //! * [Python's Sphinx tool] //! * [Doxygen] //! * [`JSDoc`] //! * [`JavaDoc`] //! + Other new languages with Markdown tooling //! * [Julia][7] has a [built-in documentation system][8] //! * [Elixir][9] has [`ex_doc`][10] //! - [Rust 1.3 release announcement][11] //! - Rust's package hosting: [crates.io][12] //! + [Crater][13] for testing for backwards compatibility //! - [Semantic versioning][14] //! + ["Stability as a Deliverable"][15]: Rust official blog post on //! version stability, backwards compatibility, and release channels. //! - [The Rust book chapter on `rustdoc`][16] //! //! [2]: https://github.com/rust-lang/rfcs/issues/1061 //! [Python's Sphinx tool]: http://sphinx-doc.org //! [Doxygen]: http://www.stack.nl/~dimitri/doxygen/ //! [`JSDoc`]: http://usejsdoc.org //! [`JavaDoc`]: http://www.oracle.com/technetwork/articles/java/index-jsp-135444.html //! [7]: http://julialang.org //! [8]: http://julia.readthedocs.org/en/latest/manual/documentation/ //! [9]: http://elixir-lang.org //! [10]: https://github.com/elixir-lang/ex_doc //! [11]: http://blog.rust-lang.org/2015/09/17/Rust-1.3.html //! [12]: https://crates.io //! [13]: https://github.com/brson/taskcluster-crater //! [14]: http://semver.org //! [15]: http://blog.rust-lang.org/2014/10/30/Stability.html //! [16]: https://doc.rust-lang.org/book/second-edition/ch14-02-publishing-to-crates-io.html#making-useful-documentation-comments //! //! # Follow/Support //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Patreon //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) /// This is a sample structure, to demonstrate `rustdoc`/`cargo doc`. /// /// All of this will be attached to the structure definition when you see it /// live on the site. If you need to document members, you can do it inline! /// /// It's worth taking a look at the [source] for this: you can see how private /// and public fields are handled differently in the documentation. /// /// [source]: /src/show_notes/e001.rs.html pub struct TVShow { /// Here is a string telling us what the theme song was. pub theme: String, /// Here is the year the show premiered. pub year: i32, /// Here is the director---but (s)he's rather shy and private. director: String, } /// You can also document the implementation. This is usually *not* going to be /// something you particularly need with a `struct`, because you can just /// attach the documentation to the `struct` itself. However, it *is* the kind /// of thing that could be useful if you are implementing a `trait`. (More on /// that in a later episode!) impl TVShow { /// This documents a fairly ho-hum structure constructor. /// /// ```ignore /// let a_struct = TVShow::new("The Answer", 42, "Joss Whedon"); /// ``` pub fn new(theme: &str, year: i32, director: &str) -> TVShow { TVShow { theme: theme.to_string(), year, director: director.to_string(), } } } /// This documents a plain-old function. /// /// The same basic rules apply as with functions bound to structs; the only /// real difference is that the docs for this won't be attached to a `struct` /// but to the module. pub fn use_members() { let firefly = TVShow::new("You can't take the sky from me!", 2001, "Joss Whedon"); println!( "Firefly (come on, sing along: \"{:?}\"): {:?}/{:?}", firefly.theme, firefly.year, firefly.director ); } ================================================ FILE: src/e002.rs ================================================ //! Something borrowed, something... moved? //! //! - **Date:** October 12, 2015 //! - **Subject:** The `struct` data type constructor, and the basics of //! Rust's "ownership" concept and "borrowing" and "moving". //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e002.mp3 //! //! //! //! # Notes //! //! Today's episode discusses, and the associated source code demonstrates, //! a few basic behaviors of structs... including borrowing! //! //! After taking a short look at one of Rust's basic approaches to creating new //! types, we dive into a *fairly* thorough overview of how borrowing works in //! fairly run-of-the-mill Rust code. This is a basic introduction, and as such //! I'm not getting into things like heap-allocated memory (`Box`) or dealing //! with `move` semantics with threads or closures. (I haven't actually figured //! those out well enough yet to write something like this for them!) //! //! As usual, you'll want to have the [`src`] open to see what I'm doing with //! the components documented below. //! //! [`src`]: /src/show_notes/e002.rs.html //! //! # Links //! //! - `rustfmt` -- a tool for formatting Rust code //! + [repo][1] //! + ["rustfmt-ing Rust`][2] //! + [Reddit discussion][3] //! - RFC for incremental compilation //! + [Text of the RFC][4] //! + [GitHub pull request][5] //! //! [1]: https://github.com/nrc/rustfmt //! [2]: http://www.ncameron.org/blog/rustfmt-ing-rust/ //! [3]: https://www.reddit.com/r/rust/comments/3nt2vm/rustfmting_rust_please_help_me_rustfmt_the_rust/ //! [4]: https://github.com/nikomatsakis/rfcs/blob/incremental-compilation/text/0000-incremental-compilation.md //! [5]: https://github.com/rust-lang/rfcs/pull/1298 //! //! # Follow/Support //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Patreon //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) /// This struct is simple but useful to see how borrowing and moving work. #[derive(Debug)] pub struct Circle { /// X position of the circle's origin. pub x: f64, /// Y position of the circle's origin pub y: f64, /// Radius of the circle pub r: f64, } /// Demonstrates how borrowing works with plain old functions. pub fn demonstrate_ownership() { // Just create a couple circles whose origin is at the origin. let immutable = Circle::origin(14.0); let mut mutable = Circle::origin(12.0); // Borrow an immutable one immutably. borrow(&immutable); // You can't borrow an immutable type mutably. // borrow_mut(&mut immutable); // You can borrow a mutable type immutably, *or* mutably. borrow(&mutable); borrow_mut(&mut mutable); println!( "Updated the radius of the mutable reference: {:}", mutable.r ); // If I move an object, I can no longer access it afterward. If you // uncomment the following line, you'll see that the Circle instances are // no longer accessible. Note that moving and borrowing are orthogonal to // mutability. It's not accessible after this because it actually gets // dropped, i.e. de-allocated. move_circle(immutable); move_circle(mutable); // println!("Immutable: {:?}", immutable); // println!("Mutable: {:?}", mutable); } /// Demonstrates general borrowing of an immutable reference. pub fn borrow(ref_to_circle: &Circle) { // I can access but not change the values. println!( "Immutable reference-- origin: {:},{:} | Radius: {:}", ref_to_circle.x, ref_to_circle.y, ref_to_circle.r ); // You can uncomment this to see the compiler error if you try to *change* // the contents. // ref_to_circle.r *= 2.0; // Similarly, if you try to reassign the reference itself, it will fail: // *ref_to_circle = Circle::new() } /// Demonstrates general borrowing of a mutable reference. pub fn borrow_mut(mutable_ref_to_circle: &mut Circle) { // I can still access these values, of course. println!( "Mutable reference-- origin: {:},{:} | Radius: {:}", mutable_ref_to_circle.x, mutable_ref_to_circle.y, mutable_ref_to_circle.r ); // But I can also update the values. mutable_ref_to_circle.r *= 2.0; } /// Demonstrates general moving of an instance. pub fn move_circle(moved_circle: Circle) { println!("Moved a circle: {:?}", moved_circle); // Note that this is an immutable type: this won't compile. // moved_circle.r *= 2.0; // We own the object, but it's still immutable, so we can't reassign the // name as we like. // moved_circle = Circle::new(4.5, 9.0, 18.0); } /// Implement some methods on the `Circle`. /// /// This lets use demonstrate both how methods work in general and specifically /// how they interact with the idea of ownership. impl Circle { /// Creates a `Circle` instance centered on the "origin" (x = 0, y = 0). fn origin(r: f64) -> Circle { Circle { x: 0.0, y: 0.0, r } } /// Creates a `Circle` instance centered on specified x, y values. pub fn new(x: f64, y: f64, r: f64) -> Circle { Circle { x, y, r } } /// Returns the value of `Circle.x`, borrowing an immutable reference to /// the circle to do it. /// /// Because the reference is immutable, if you tried to do this--- /// /// ```ignore /// self.x = 10; /// ``` /// /// ---the compiler would not allow it. pub fn x_by_ref(&self) -> f64 { println!("Taking a reference."); // The reference is immutable. self.x } /// Returns the value of `Circle.x`, borrowing a mutable reference to the /// circle and changing the value (demonstrating a situation in which you /// would want to use a mutable rather than immutable reference). pub fn x_by_mut_ref(&mut self) -> f64 { println!("Taking a mutable reference."); self.x += 1.0; self.x } /// Returns the value of `Circle.x`, taking ownership of the circle. As a /// result of the change in ownership, the circle goes out of scope after /// the method returns, so the circle instance will be inaccessible after /// that. /// /// Note that the item is taken as immutable, so attempting to change the /// internals will still fail. **Ownership is orthogonal to immutability.** pub fn by_take(self) -> f64 { println!("Taking ownership, not just borrowing a reference. INTENSE."); self.x } /// Returns the value of `Circle.x`, taking ownership of a mutable circle. pub fn by_take_mut(mut self) -> f64 { println!("Taking ownership *and* mutating all the things."); self.x += 14.0; self.x } } /// Demonstrates how the same concepts apply when dealing with methods. pub fn demonstrate_method_ownership() { // There are several ways to construct struct types. The first is a plain // struct constructor. let basic = Circle { x: 1.0, y: 2.0, r: 5.0, }; // The next is using a constructor. let mut mutable = Circle::new(14.0, 12.0, 10.0); // Constructors can have default behavior, like this one. let immutable = Circle::origin(12.0); println!("{:?}", basic); println!("{:?}", immutable); println!("{:?}", mutable); // Now we can see how different method calls work. When we borrow a // reference, there is no consequence: during the life of the method, the // immutable object is "borrowed" by the `x_by_ref` method. Ownership returns // to the `main` function when it returns. let by_ref_x = immutable.x_by_ref(); println!("By reference: {}", by_ref_x); // The same is true of a method that borrows a mutable reference. Note, // however, that since the reference is mutable, it can change the contents // of the struct. print!("Original x_by_mut_ref x value: {}... ", mutable.x); let by_mut_ref_x = mutable.x_by_mut_ref(); println!("After calling `x_by_mut_ref`: {}", by_mut_ref_x); // Note that both of these struct instances are still available for `main` // to use once they return from the method call: println!( "immutable's y: {} | mutable's r: {}", immutable.y, mutable.r ); // A method that takes ownership can still return a value. However, it has // a very different behavior in terms of the struct instance, in a way that // seems surprising compared to languages without the concept of "borrowing" // vs. "taking" (C, Java, Python, etc.). // // Run a method that takes ownership rather than just borrowing a reference. // The value returned is as expected. However, the item has been *moved*, // not just borrowed. That is, `main` no longer owns it---`by_take` took // over the ownership. Once `by_take` ended, `immutable` actually gets // deconstructed ("dropped") because it went out of scope. As a result, the // following line won't compile (you can uncomment it to see for yourself): let by_take_x = immutable.by_take(); println!("By take: {}", by_take_x); // println!("Does the circle still exist? {:?}", immutable); // Likewise, if we use the mutable circle with the method which takes // ownership and mutates it, we can get the value back as before, but the // circle will have been dropped when the `by_take_mut` call ended. let by_mut_take_x = mutable.by_take_mut(); println!("By mutable take: {}", by_mut_take_x); // println!("Does the mutable circle still exist? {:?}", mutable); } ================================================ FILE: src/e003.rs ================================================ //! No. more. nulls. //! //! - **Date:** October 21, 2015 //! - **Subject:** Enumerated (`enum`) types, pattern matching, and meaningful //! return values. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e003.mp3 //! //! //! //! # Notes //! //! Today's episode discusses, in order: //! //! - Enumerated types, with an eye to the difference between structs and //! enums, and to the differences between `enum`s in C and in Rust. //! - Pattern matching, with a focus on using them with enumerated types and //! some discussion about how they differ from `switch` blocks in C-like //! languages. //! - Using the `Option` and `Result` enumerated types with pattern matching //! to provide meaningful returns from functions safely. //! //! ## Order //! There is a specific order to the examples below, and it is *not* the //! automatically-alphabetized order rendered by `rustdoc`. Instead, you should //! work through in the sequence they appear in the [source]: //! //! 1. [`RelatedishThings`] //! 2. [`demonstrate_basic_enumeration`] //! 3. [`demonstrate_match`] //! 4. [`get_an_option`] //! 5. [`demonstrate_option`] //! 6. [`get_a_result`] //! 7. [`demonstrate_result`] //! //! [source]: /src/show_notes/e003.rs.html //! [`RelatedishThings`]: /show_notes/e003/enum.RelatedishThings.html //! [`demonstrate_basic_enumeration`]: /show_notes/e003/fn.demonstrate_basic_enumeration.html //! [`demonstrate_match`]: /show_notes/e003/fn.demonstrate_match.html //! [`get_an_option`]: /show_notes/e003/fn.get_an_option.html //! [`demonstrate_option`]: /show_notes/e003/fn.demonstrate_option.html //! [`get_a_result`]: /show_notes/e003/fn.get_a_result.html //! [`demonstrate_result`]: /show_notes/e003/fn.demonstrate_result.html //! //! ## Links //! //! - New Rustacean [Pull Request #1][link-1] //! - Work on IDE support! //! + [Landing page][link-2] //! + My chosen tool: [JetBrains/IntelliJ][link-3] //! - [Rustlings][link-4] //! - [Rust FFI Omnibus][link-5] //! //! [link-1]: https://github.com/chriskrycho/newrustacean.com/pull/1 //! [link-2]: https://www.rust-lang.org/ides.html //! [link-3]: https://github.com/alexeykudinkin/intellij-rust //! [link-4]: https://github.com/carols10cents/rustlings //! [link-5]: http://jakegoulding.com/rust-ffi-omnibus/basics/ //! //! # Follow/Support //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Patreon //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) /// Just exists to be used as an element in `RelatedishThings`. #[derive(Debug)] pub struct PreexistingStruct { pub some_int: i32, pub some_string: String, } /// An enumeration can *hold* a variety of types. This one shows you a few. /// /// Note: using an `enum` this way is actually crazy. The types should usually /// have some relationship to each other. Here, they don't. The *only* reason I /// have them together like this is to show you that these aren't just integers. /// Enums in Rust can have members of any other type. /// /// As [Rust by Example][1] [puts it][2]: /// /// > Any variant which is valid as a `struct` is also valid as an `enum`. /// /// What's the difference between an `enum` and `struct`? An `enum` is only ever /// *one* of the options which comprise it, whereas a `struct` is always *all* /// the elements which comprise it. /// /// One enormous benefit of `enum` types is that, when they are the return value /// of a function (as in the examples below), they *must* be handled. /// /// [1]:http://rustbyexample.com/ /// [2]: http://rustbyexample.com/custom_types/enum.html #[derive(Debug)] pub enum RelatedishThings { /// This doesn't have a value other than being RelatedishThings::Unit. Unit, /// It could be a tuple struct, with basically any value type embedded. SomeName(String), SomeValue(i32), /// It can be a full-on struct-type construct. ComplexData { description: String, number: String, }, /// And it can use other complex data types within those, of course. ReusedStructure(PreexistingStruct), } /// Shows how returning a `RelatedishThings::Unit` instance works. fn get_unit() -> RelatedishThings { RelatedishThings::Unit } /// Shows how returning a `RelatedishThings::SomeName` instance works. fn get_name() -> RelatedishThings { RelatedishThings::SomeName("New Rustacean".to_string()) } /// Shows how returning a `RelatedishThings::SomeValue` instance works. fn get_value() -> RelatedishThings { RelatedishThings::SomeValue(42) } /// Shows how returning a `RelatedishThings::ComplexData` instance works. fn get_complex_data() -> RelatedishThings { RelatedishThings::ComplexData { description: "A fun podcast!".to_string(), number: "e003".to_string(), } } /// Shows how returning a `RelatedishThings::ReusedStructure` instance works. fn get_reused_structure() -> RelatedishThings { // First create a struct from our (silly) PreexistingStruct type. let s = PreexistingStruct { some_int: 42, some_string: "Hey".to_string(), }; // Then bundle that value into the returned enum type. RelatedishThings::ReusedStructure(s) } /// Shows how the result of an enum comes back as increasingly complex data. /// /// Note that while we *could* have a numeric value associated with each /// enumerated value (as in a C/C++ `enum`), we don't *have* to. The value of /// an enumeration in Rust is *which enumerated value it is*, and nothing more /// unless you specify something more. pub fn demonstrate_basic_enumeration() { print!( "{:?}\n{:?}\n{:?}\n{:?}\n{:?}\n", get_unit(), get_name(), get_value(), get_complex_data(), get_reused_structure() ); } /// Shows in a bit more detail how `match` works. /// /// Note that the pattern matches include matching against numbers, tuple types, /// and more. Big takeaways: /// /// - You can match against all sorts of types. /// - You have to match exhaustively. Handle "everything else" with `_` as the /// sole component of the match arm. /// - You can destructure complex types into their components. You can ignore /// components of complex types with `_` as well. pub fn demonstrate_match() { // You can match on numbers... let answer = 42; let question = match answer { // That includes individual numbers or ranges. 0 => "What do you get when you divide by this? PROBLEMS.", 1..=41 => "This is all pretty normal, right?", 42 => "Life, the universe, and everything, eh? (Canadian version)", // What about catching *everything else*? Use `_`. _ => "I've got nothing useful to say here.", }; println!("I asked: '{:}'; the answer was: {:}", question, answer); // or letters... let character = 'C'; match character { 'A'..='B' => println!("Nope, not those letters."), 'C' => println!("Why, yes, my name *does* start with a 'C'"), 'D'..='z' => println!("None of those either."), _ => println!("That's not even a letter!"), } // or more complex types... const THREE: u8 = 3; const TWO: u8 = 2; let some_tuple = (THREE, TWO); match some_tuple { // You can match on the full tuple with specific values. (THREE, TWO) => println!("Got both!"), // You can match on only part of it; note that these match the cases where both are *not* // filled with the value specified in the first arm. (THREE, _) => println!("Got three only."), (_, TWO) => println!("Got two only."), // You can also destructure the elements of the tuple into values to be // used in the body of the expression, not just ignore them with `_`. (a, b) => println!("Got weird other stuff: {:}, {:}", a, b), } } /// Shows how this is used in a more meaningful context, with a standard type. pub fn get_an_option(get_it: bool) -> Option { if get_it { // Returns an `Option` enum in the `Some` type. Some(std::f64::consts::PI) } else { // Returns an `Option` enum in the `None` type. This might look like the // `null` type you'd see elsewhere; it isn't. See below. None } } /// Shows how an option type works in practice. pub fn demonstrate_option() { // Just demonstrate how it gets printed. let some = get_an_option(true); let none = get_an_option(false); print!("{:?}\n{:?}\n", some, none); // You can see, from printing the values above, that the `some` is (as you // would expect from seeing how enums work in general) not a plain value; // it's wrapped in `Some`! However, we can unwrap it to get at the actual // value: let some_value = some.unwrap(); println!("{:?}", some_value); } /// Shows how to return either a meaningful result or an error as an enum. /// /// The `Result` type is a standard pattern for handling cases where the result /// of a given function may be an error. No more of the C/C++ pattern of passing /// in/out arguments so that you can get a normal/error-indicating return code. /// Instead, you just return a `Result`, and then `match` on that value to /// handle it. pub fn get_a_result(succeeds: bool) -> Result { if succeeds { #[allow(clippy::approx_constant)] Ok(2.718_281_828) } else { Err("Huh. This didn't go as planned.".to_string()) } } /// Shows how a `Result` type works in practice. /// /// A `Result` is an `enum` (which can be converted to the `Option` type), which /// lets us hand back, and then handle, the results of a given function easily. pub fn demonstrate_result() { // First of all, what is the result of this `match`? What would it be if we // changed the call to `get_a_result(false)` instead? match get_a_result(true) { Ok(value) => println!("The value was: {:}", value), Err(message) => println!("ERROR: {:}", message), } // Note that you can readily convert the `Ok` and `Err` terms in a `Result` // to `Option`s! let an_ok = get_a_result(true); let an_err = get_a_result(false); print!("{:?}\n{:?}\n", an_ok.ok(), an_err.err()); // Let's demonstrate the flip-side (i.e. the `None` and `Some` bits). Note // how the methods behave: `Result::ok()` -> `Some` for the `Ok` enum and // `None` for the `Err` enum; and `Result::err()` does the inverse.. let another_ok = get_a_result(true); let another_err = get_a_result(false); print!("{:?}\n{:?}\n", another_ok.err(), another_err.ok()); } ================================================ FILE: src/e004.rs ================================================ //! Functionalized //! //! - **Date:** October 29, 2015 //! - **Subject:** Functions, methods, closures, and function as arguments! //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e004.mp3 //! //! //! //! # Notes //! //! This week's episode covers the basics of all sorts of functions: normal //! functions, methods, and closures. //! //! ## Closures //! - [An explanation (in Ruby) by Martin Fowler][notes-1] //! - [Rust book][notes-2] //! - [Rust by Example][notes-3] //! - ["What is a closure?" (Progammers Stack Exchange)][notes-4] -- the first //! answer is the best, but the second answer may be a helpful stepping //! stone for people just getting their heads around this and coming from //! OOP languages like C++ or Java (even though I disagree with the //! explanation in some ways). //! - ["What is a closure?" (Stack Overflow)][notes-5] -- careful, thorough //! answer using JavaScript as an example. //! //! [notes-1]: http://martinfowler.com/bliki/Lambda.html //! [notes-2]: https://doc.rust-lang.org/book/closures.html //! [notes-3]: http://rustbyexample.com/fn/closures.html //! [notes-4]: http://programmers.stackexchange.com/questions/40454/what-is-a-closure //! [notes-5]: http://stackoverflow.com/questions/36636/what-is-a-closure //! //! # Links //! //! - [Exercism][link-1] (hat tip: [Lechindanier on GitHub][link-2]) //! - [Rust Learning][link-3] //! - [Rust and Swift (viii)][link-4] //! //! [link-1]: http://exercism.io/languages/rust //! [link-2]: https://github.com/Lechindianer //! [link-3]: https://github.com/ctjhoa/rust-learning //! [link-4]: http://www.chriskrycho.com/2015/rust-and-swift-viii.html //! //! # Follow/Support //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Patreon //! + [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) /// Create a module so we can see public/private behavior. /// /// We will discuss modules in more detail in the future. mod struct_container { /// Shows how methods work. Elaborates only a little on the e001 examples. pub struct MethodDemonstrator { // Public data. pub an_int: i64, pub a_string: String, // Private data. /// A tuple holding a floating point value and a string slice. (We'll /// discuss string slices in a future episode.) a_tuple: (f64, String), } impl MethodDemonstrator { /// A standard constructor pattern. /// /// You've seen this before, in the e001 code! /// /// Note that Rust doesn't have constructors in the same sense as C++ /// or Java: you can construct a `MethodDemonstrator` just as this /// function does somewhere else. Using `new` is a convenient /// convention, so you can just call `MethodDemonstrator::new()` to get /// an instance, rather than needing to worry about the details of the /// struct. /// /// This is particularly important because not all types are /// necessarily public; you may not be able to construct a given /// `struct` *correctly* if it has hidden types, especially computed /// properties, which should be initialized during its construction. pub fn new() -> MethodDemonstrator { MethodDemonstrator { an_int: 0, a_string: "Nothin' into nothing, divide the nothin'...".to_string(), a_tuple: (2.0, "Twice 1.0".to_string()), } } /// A standard struct instance method. /// /// Note that *instance* methods take a reference to `self` as the /// first argument. It *needs* to be a reference for normal methods, /// because if it isn't, the struct instance will be moved into the /// function---the method will own, not just borrow---the reference, /// and after the method call ends, the item will be destroyed. /// /// Of course, if you need to write a custom destructor for a more /// complex type, you now have a pretty good idea how to write the first /// argument to that method... pub fn method(&self) { println!( "The values of the object are: {:}, {:}, {:}, {:}", self.an_int, self.a_string, self.a_tuple.0, self.a_tuple.1 ); } /// A getter for data which is not publicly accessible in the type. /// /// If you try to access the tuple contents directly, e.g. with an /// instance of the struct *outside this module*, you will fail. (See /// the example in `demonstrate_methods`.) /// /// The data can be accessed by the struct itself, however, so you can /// get or set the data, as here. /// /// We use `clone` because we need to get not the items themselves /// (which we could otherwise only get as references) but their values; /// the `clone` method is from the `Clone` trait, which is available on /// many basic types in the system. Again, we will return to `trait`s in /// a later episode. pub fn get_hidden_data(&self) -> (f64, String) { self.a_tuple.clone() } } } /// Shows how to use both struct and instance methods. /// /// Note that struct methods are called with the `::` syntax, which is the same /// as the module syntax! We'll come back to this soon. Note as well that the /// `.` syntax used for instance methods corresponds to the use of `self` (in /// whatever form) in pub fn demonstrate_methods() { // Just builds a struct instance as expected. let a_struct = struct_container::MethodDemonstrator::new(); // Call a basic method using `.` notation (which supplies `self` as the // first argument, in the appropriate fashion for the method). a_struct.method(); // This won't work: the `a_tuple` member is private. // // println!("{:?}", a_struct.a_tuple); // // However, we can get at the data if the struct gives us access: println!("{:?}", a_struct.get_hidden_data()); } /// Shows how to take a function as an argument. /// /// Note that this involves specifying a *generic* (the `` syntax), bounded /// by a `trait` (the `where...` syntax), a concept to which we will return in /// much more detail in a few episodes. pub fn apply_function_to_i64(a_number_function: F, the_number: i64) -> i64 where F: Fn(i64) -> i64, { let result = a_number_function(the_number); println!("{:?}", result); result } /// Show how to call a function with a function as an argument. /// /// Both normal functions and closures can be passed as arguments to functions /// which accept functions as arguments, as long as their type definition /// matches the requirements of the destination function. pub fn demonstrate_function_arguments() { /// Implements the signature required for `apply_function_to_i64`. /// /// Note that this is a nested function definition! It is unavailable /// outside the `demonstrate_function_arguments` body. fn double(n: i64) -> i64 { n * 2 } // You can pass a normally defined function. assert_eq!(apply_function_to_i64(double, 2), 4); // You can also pass a closure, defined inline or standalone. // Inline closure definition: assert_eq!(apply_function_to_i64(|n| n * n, 5), 25); // Standalone closure definition let cube = |n| n * n * n; assert_eq!(apply_function_to_i64(cube, 9), 729); // You cannot use a function which does not meet the definition of the // target function, however, so this won't compile: } /// Shows how closures can act on elements within their environment. /// /// Closures are handy for more than merely a quick and easy way to write a /// callback; they also serve as one possible way to hide information or /// implementation details. While that's not as strictly necessary in Rust as it /// is in e.g. JavaScript, it still has a great deal of utility, especially in /// more functional programming styles. pub fn demonstrate_closure_environment() { /// Returns a closure which has access to the internal contents of this /// function even after it goes out of scope. fn get_a_closure() -> Box f64> { let x = 14.0; // Now we define a closure. I'll explain the bits with `move` and // `Box::new` here next week; for now, suffice it to say that they're // necessary for Rust's memory guarantees and scoping behavior. let do_with_captured_x = move |n| n * x; Box::new(do_with_captured_x) } // Now call the closure. Note that even though we're now in a scope where // the value of `x` defined doesn't exist (try `println!("{:}", x);` if you // want to verify this), the closure still has access to it. let the_closure = get_a_closure(); assert_eq!(the_closure(2.0), 28.0); /// Calls whatever function you hand it with the value 14.0 fn takes_a_closure_with_14(f: F) -> f64 where F: Fn(f64) -> f64, { f(14.0) } // Note that the closure can interact with *this* environment as well as the // items handed to it by the function which calls it, because the `y` term // is available in its surrounding scope. let y = 3.0; assert_eq!(takes_a_closure_with_14(|n| n * y), 42.0); } #[test] fn demonstrate() { demonstrate_function_arguments(); demonstrate_methods(); demonstrate_closure_environment(); } ================================================ FILE: src/e005.rs ================================================ //! Allocate it where? //! //! - **Date:** November 8, 2015 //! - **Subject:** Returning functions from other functions, and thinking //! about the stack, the heap, and reference types. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e005.mp3 //! //! //! //! # Notes //! //! This episode, we look at returning functions from other functions, and as //! part of that discuss some basics about the stack and the heap---and why we //! need to care about them for returning functions. //! //! The functions themselves are not especially interesting; they just show you //! the basic form you use to return functions from other functions, and how to //! then use them in another function. You'll want to take a detailed look //! instead at the documentation for each (or just read the [source][notes-1]!), //! because that's where the meat of the discussion in this week's code is. //! //! ## Corrigenda //! //! - Steve Klabnik [pointed out][notes-2] that my description of `Vector` //! types as totally heap-allocated was misleading. It's better to say that //! the *contents* of the `Vector` -- its data -- is heap-allocated, while //! the memory for the smart pointer and associated metadata are allocated //! on the stack. I had this in mind, and sort of alluded to it earlier in //! the discussion, but the way I actually said it was misleading at best. //! //! - Chad Sharp (@crossroads1112 on GitHub) [clarified][notes-3] that in C99, //! C *does* support dynamic array allocation, though it became optional for //! compilers to implement it as of C11. I forgot about this because I spend //! so much of my time dealing with Visual C++, which does not support //! dynamic array allocation. (Notably, Visual C does; it is Visual C++ //! which does not: remember, C and C++ are related but distinct languages.) //! //! Thanks to Steve and Chad for their helpful feedback! //! //! [notes-1]: /src/show_notes/e005.rs.html //! [notes-2]: https://users.rust-lang.org/t/new-rustacean-podcast-e005-allocate-it-where-2015-11-08/3153/13?u=chriskrycho //! [notes-3]: https://github.com/chriskrycho/newrustacean.com/issues/7 //! //! # Links //! //! - [Rust 1.4 release announcement][links-1] //! - ["Clarify (and improve) rules for projections and well-formedness"][links-2] //! - [MSVC support tracking issue][links-3] //! - [Rust 1.4 full release notes][links-4] //! - ["What and where are the stack and the heap?"][links-5] //! //! [links-1]: http://blog.rust-lang.org/2015/10/29/Rust-1.4.html //! [links-2]: https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md //! [links-3]: https://github.com/rust-lang/rfcs/issues/1061 //! [links-4]: https://github.com/brson/rust/blob/relnotes/RELEASES.md //! [links-5]: http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap //! //! # Sponsors //! //! - reddraggone9 //! - [Chris Patti][sponsors-1] //! //! [sponsors-1]: http://podcastinit.com //! //! ## Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! # Follow //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) /// Creates a function which doubles an integer. /// /// Note that it doesn't have `Fn(i32) -> i32` as its return type, but rather /// `Box i32`. At present, functions have to be explicitly /// heap-allocated. If we tried to return just a `Fn` type, we'd end up in a /// tangled mess of lifetime and ownership (whether with a regular function, as /// here, or a closure as in `doubler_closure_factory`). pub fn doubler_factory() -> Box i32> { /// The doubler function we will return. fn double(n: i32) -> i32 { n * 2 } Box::new(double) } /// Creates a closure which doubles an integer. /// /// Compare with the function above: this is basically identical to /// `doubler_factory`, the only difference being that in this case, we return a /// closure rather than a standalone function. That has substantial /// ramifications for using closures and named functions, of course; refer to /// the discussion in [e004][e004] for details /// /// [e004]: /show_notes/e004/ pub fn doubler_closure_factory() -> Box i32> { // We could also write this as `Box::new(|n| n * 2)`, of course. let doubler = |n| n * 2; Box::new(doubler) } /// Uses the `doubler_factory` to get a function which doubles a number. /// /// By contrast, here's a function which simply won't compile: /// /// ```rust,ignore /// fn will_not_compile() -> Fn(i32) { /// let a_closure = |n| println!("Seriously. This won't compile. {}", n); /// a_closure /// } /// ``` /// /// And another. This gets us a bit closer, because you actually have both a /// concrete reference type and a lifetime. However, it still won't compile, /// because after `get_normal_function_with_lifetime` ends, the function goes /// out of scope and the reference points to junk value. /// /// ```rust,ignore /// fn get_normal_function_with_lifetime() -> &'static (Fn(i32) -> i32) { /// fn multiply_by_3(n: i32) -> i32 { /// n * 3 /// } /// /// return &multiply_by_3; /// } /// ``` /// /// Even this approach doesn't work, because although the *function* lives on /// past the end of the `get_normal_external_fn_with_lifetime`, the reference /// created during that function call *doesn't*. /// /// ```rust,ignore /// fn multiply_by_4(n: i32) -> i32 { n * 4 } /// /// fn get_normal_external_fn_with_lifetime() -> &'static (Fn(i32) -> i32) { /// &multiply_by_4 /// } /// ``` /// /// The solution, as we saw at the beginning, is to use `Box::new` to /// heap-allocate the function result instead. pub fn demonstrate_function_returns() { let double = doubler_factory(); println!("{:}", double(14)); } ================================================ FILE: src/e006.rs ================================================ //! Modularize this! //! //! - **Date:** November 16, 2015 //! - **Subject:** Designing APIs, and using packages ("crates") and modules //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e006.mp3 //! //! //! //! # Notes //! //! Today, we are talking about modules, packages, and APIs in Rust. Taking a //! bit of a breather after some pretty hard material the last few weeks. //! //! For reference, the [Rust book][notes-1] section on [Crates and //! Modules][notes-2] will be very helpful. //! //! [notes-1]: http://doc.rust-lang.org/book/ //! [notes-2]: http://doc.rust-lang.org/book/crates-and-modules.html //! //! ## Corrigenda //! //! I accidentally called this episode 5, instead of episode 6. *Whoops.* //! //! Just before the 15:00 mark, while discussing libraries, I referred to //! "e006.md" when I meant to say "e006.rs". Slips of the tongue inspired by the //! fact that Rust (delightfully) uses Markdown for its documentation. //! //! # Links //! //! - [Roguelike in Rust][links-1] //! - [Yehuda Katz on Ruby FFI][links-2] //! //! [links-1]: http://jaredonline.svbtle.com/roguelike-tutorial-table-of-contents //! [links-2]: https://engineering.intercom.io/yehuda-on-rust-with-ruby/ //! //! # Module Docs! //! //! As you've no doubt noted if you've actually looked at the show notes along //! the way, these are in fact module docs! Because we're inside a module marked //! off by being a file, we *have* to use the `//!` style of documentation //! comments to mark them off. However, as you'll see below, if we structure or //! declare modules in other ways, we will not have the same restriction. //! //! # Sponsors //! //! - reddraggone9 //! - [Chris Patti][sponsors-1] //! //! [sponsors-1]: http://podcastinit.com //! //! ## Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! # Follow //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) /// This is an internal module. Note that it isn't public. /// /// Modules may have any kind of "item" local to them. "Items" in Rust are /// things like functions, structs, enums, traits, type definitions, and other /// modules. /// /// Modules have namespaces mod internal_module { /// A module function, demonstrating module-public function status. /// /// This function is public to the `internal_module`, but because the module /// itself isn't public, neither is the function. It is available to /// anything which uses `internal_module`, however, as it is public at the /// function level. pub fn a_public_module_fn() { println!("At `internal_module::a_public_module_fn()`."); a_private_module_fn(); } /// Another module function, demonstrating module-private function status. /// /// Since this function is private to the module, it is inaccessible to /// external callers (see below in `use_modules_internal()`). However, it is /// accessible as normal to other functions within its own module, and thus /// can be called by `a_public_module_fn()`. fn a_private_module_fn() { println!("At `internal_module::a_private_module_fn()`."); } } /// This is an internal module which *is* public. /// /// External modules therefore have access to this module, not just other /// modules within the immediate parent `e006` (file) module. pub mod public_internal_module { /// A public function in a public module. /// /// Note that the name of this function is the *same* as the public function /// in `internal_module` above! This is one of the values of namespacing. pub fn a_public_module_fn() { println!("At `public_internal_module::a_public_module_fn()`."); some_private_fn(); } /// A private function in a public modules. fn some_private_fn() { println!("At `public_internal_module::some_private_fn()`."); } } /// Demonstrates the use of modules and namespaces. /// /// Modules can access other modules which are contained in the same parent /// module as them regardless of the privacy settings. However, they cannot /// access non-public modules which don't have the same immediate parent. pub fn use_modules_internal() { println!("At `use_modules_internal()`."); // Calling another module's function is quite straightforward. internal_module::a_public_module_fn(); // Note that we cannot access the internal module's private function. If you // uncomment the following line, you will see a compile error indicating // that the function is private. // // internal_module::a_private_module_fn(); // // Similarly, as you would expect, we have access to public functions in // public modules, but no access to private functions in public modules. (We // have already seen this, in fact, just in file-based, rather than // declaration-based, modules.) public_internal_module::a_public_module_fn(); } // What if we wanted to use *any* public function from a given module? We // can simply `use` that module. // // It is worth quoting the Rust book here: // // > **Note:** Unlike in many languages, use declarations in Rust do not // > declare linkage dependency with external crates. Rather, `extern crate` // > declarations declare linkage dependencies. pub mod demonstrate_namespacing { /// We can `use` other module's contents. use crate::e006::public_internal_module::*; /// We can also alias other modules. Note that though we don't use this /// until `demonstrate_aliased_calls()`, we have to put any `use` statements /// before any other contents of the module (so this can't go between the /// `demonstrate_globbed_calls()` and `demonstrate_aliased_calls()` function /// definitions). use crate::e006::internal_module as im; /// Demonstrates how glob-imported `use`s works. pub fn demonstrate_globbed_calls() { println!("At `demonstrate_namespacing::demonstrate_globbed_calls()`."); // Having imported *everything* from `public_internal_module`, we can call // its public functions directly. a_public_module_fn(); } /// Demonstrates how aliased namespaces work. pub fn demonstrate_aliased_calls() { println!("At `demonstrate_namespacing::demonstrate_aliased_calls`."); im::a_public_module_fn(); } } /// Demonstrates that modules can be `use`d within functions. pub fn demonstrate_use_inside_function() { use crate::e006::demonstrate_namespacing as dn; println!("At `demonstrate_use_inside_function()`."); dn::demonstrate_globbed_calls(); } /// Give an example of nested modules. /// /// Of course, *all* the modules in this file are nested: they are part of the /// file-level `e006` module. Here, though, we see an explicit example of that. pub mod demonstrate_nesting { /// This is just a nested module. pub mod a_nested_module {} // An example of re-exporting another module's contents publicly. // // Remember, this module was initially part of a private module (but one // within the `e006` parent module, and therefore accessible to us.) // We are re-exporting its `a_nested_module` contents, with a different // name, as a public module. When you look at the docs, you'll see this // function name within the module, with the docs from the definition of the // function in the `internal_module` above! pub use crate::e006::internal_module::a_public_module_fn as now_public_fn; } ================================================ FILE: src/e007.rs ================================================ //! Testify //! //! - **Date:** December 13, 2015 //! - **Subject:** Testing and benchmarking, and compiler attributes. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e007.mp3 //! //! //! //! Notes //! ----- //! //! All about testing in Rust! In order, we take a look at: //! //! - Why you need tests. //! - Unit tests in other (dynamically-typed) languages vs. in Rust. //! - How to write unit tests in Rust. //! - How and why to write integration tests in Rust. //! - How and why to use benchmarks in Rust. //! //! The detailed code samples for this episode are heavy on showing; because of //! the nature of test functions, you will be best off just [reading the source] //! rather than leaning heavily on the descriptions generated by **rustdoc**. //! (The descriptions are still *there*, but they're much less useful than they //! have been in previous episodes.) In particular, the `test` module here is //! excluded because of the use of the `#[cfg(test)]` attribute marker on it. //! //! [reading the source]: /src/show_notes/e007.rs.html //! //! Because we are using the feature-gated benchmarking functionality, the //! show notes "library" can now only be compiled with the Rust nightly (as of //! 1.5, the version current as this episode is produced). //! //! One thing that isn't necessarily obvious from reading the test documentation //! in the Rust book and Rust reference: the `extern crate test` statement needs //! to be not in this module, but at the module (`lib.rs`) which defines the //! library/crate; in this case, `show_notes/lib.rs`. //! //! //! Links //! ----- //! //! - Rust Book: //! + [Testing][links-1] //! + [Attributes][links-2] //! + [Benchmark tests][links-3] //! - Rust reference: [Attributes][links-4] //! - [Diesel (Rust ORM)][links-5] //! + [31: Oxidizing an ORM][links-6] //! + [32: Bug for Bug Compatibility][links-7] //! //! [links-1]: https://doc.rust-lang.org/book/testing.html //! [links-2]: https://doc.rust-lang.org/book/attributes.html //! [links-3]: https://doc.rust-lang.org/book/benchmark-tests.html //! [links-4]: https://doc.rust-lang.org/reference.html#attributes //! [links-5]: https://github.com/sgrif/diesel //! [links-6]: http://bikeshed.fm/31 //! [links-7]: http://bikeshed.fm/32 //! //! //! Sponsors //! -------- //! //! - Chris Palmer //! - [Derek Morr][sponsors-2] //! - Luca Schmid //! - Micael Bergeron //! - Ralph Giles ("rillian") //! - reddraggone9 //! - [William Roe][sponsors-7] //! //! [sponsors-2]: https://twitter.com/derekmorr //! [sponsors-7]: http://willroe.me //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! //! Follow //! ------ //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) /// A trivial function for a trivial test. See the [source](/src/show_notes/e007.rs.html)! pub fn add(a: f64, b: f64) -> f64 { a + b } /// A trivial test of a trivial function, demonstrating `#[test]`. /// /// This test function will not be compiled into a binary; it will *only* be /// used with the test binary. Note that you *can* create standalone test /// functions as long as they are marked with the `#[test]` attribute, but in /// general, you should put it in the `test` module, see below. #[test] fn test_add() { assert_eq!(add(2.0, 2.0), 4.0); } /// A test module! /// /// A few comments: /// /// - Note the `#[cfg(test)]` attribute marker on the module. /// - Note the distinction between `#[test]` and `#[bench]`. #[cfg(test)] mod tests { // This statement gives us access to everything in the parent module, so we // don't have to use the full namespace (`show_notes::e007::add`) to get // access to the functions we want to test. use super::*; // `Bencher` is the `struct` which has the benchmarking functionality. use crate::test::Bencher; // We'll use this for demonstrating benchmarks later. use std::thread::sleep; use std::time::Duration; /// Another, equally trivial, test, this one for `#[should_panic]`. /// /// In a more meaningful scenario, we might use the `#[should_panic]` attribute /// to verify that a given function call triggers an error under conditions /// where it should, e.g. if we tried to `.unwrap` a value which didn't exist. #[test] #[should_panic] fn test_add_badly() { assert_eq!(add(2.0, 2.0), 5.0); } /// A yet more sophisticated example: `#[should_panic]` with `expected`. /// /// As the Rust book comments: /// /// > ...it's hard to guarantee that the test didn't fail for an unexpected /// > reason... /// /// The `#[should_panic]` annotation has an `expected` attribute. #[test] #[should_panic(expected = "Crazed monkeys!")] fn test_will_panic() { panic!("Crazed monkeys!"); } /// Benchmark our addition function. /// /// Note: it's trivial, so it's probably pretty quick (`0 ns/iter (+/- 0)`). /// The point is simply that it does what it says on the tin. #[bench] fn demonstrate_benchmarking(bencher: &mut Bencher) { bencher.iter(|| add(2.0, 2.0)); } /// We can also have secondary functions used to help with testing. /// /// This particular function is *stupid*; the way to do this, of course, is /// just to get the Duration directly. The only reason to have it here is to /// show that (1) `support_function()` doesn't end up in the compiled /// library, which you can check by inspecting the binary; and (2) that it /// is available for use with the benchmarker below. fn support_function(ns: u32) -> Duration { Duration::new(0, ns) } /// Benchmark a function that sleeps for 1ms every time you call it. /// /// One of the things this highlights: we have a *tiny* duration (10 ns)... /// and the test takes much, *much* longer. (I'm going to discuss this with /// the Rust community, because I don't actually understand it yet!) #[bench] fn demonstrate_benchmarking_with_sleep(bencher: &mut Bencher) { let duration = support_function(10); bencher.iter(|| sleep(duration)); } } ================================================ FILE: src/e008.rs ================================================ //! Just like something else //! //! - **Date:** 2015-12-27 //! - **Subject:** Generics, traits, and shared behavior in Rust. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e008.mp3 //! //! //! //! Notes //! ----- //! In this episode we cover---at a *very* high level---two more fundamental //! concepts in Rust programming: generics and traits. //! //! Generics gives us the ability to write types and functions which can be //! used with more than one type. Traits give us the ability to specify behavior //! which can be implemented for more than one type. The combination gives us //! powerful tools for higher-level programming constructs in Rust. //! //! ### Comments on source code //! //! Now that we have a handle on [how tests work][e007], we'll use them to //! validate the behavior of our code going forward. This is great: we can show //! that the tests do what we think. //! //! To today's point, though: we actually know even apart from whether the tests //! *run* successfully that these generic functions and the associated traits //! are behaving as we want. Failure with generics is a *compile*-time error, //! not a runtime error. //! //! [e007]: https://www.newrustacean.com/show_notes/e007/ //! //! //! Links //! ----- //! //! - Rust Book //! + [Generics][l1] //! + [Traits][l2] -- includes a discussion of *trait bounds* and *generic //! *traits* //! - Rust by Example //! + [Generics][l3] //! + [Traits][l4] //! + [Generic *traits*][l5] //! + [Traits *bounds*][l6] //! - [Generics and traits in use in Diesel][l7] //! //! [l1]: https://doc.rust-lang.org/book/generics.html //! [l2]: https://doc.rust-lang.org/book/traits.html //! [l3]: http://rustbyexample.com/generics.html //! [l4]: http://rustbyexample.com/trait.html //! [l5]: http://rustbyexample.com/generics/gen_trait.html //! [l6]: http://rustbyexample.com/generics/bounds.html //! [l7]: https://github.com/sgrif/diesel/blob/master/diesel/src/types/mod.rs //! //! //! Sponsors //! -------- //! //! - Chris Palmer //! - [Derek Morr][sponsors-2] //! - Luca Schmid //! - Micael Bergeron //! - Ralph Giles ("rillian") //! - reddraggone9 //! - [William Roe][sponsors-7] //! //! [sponsors-2]: https://twitter.com/derekmorr //! [sponsors-7]: http://willroe.me //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! //! Follow //! ------ //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) use std::fmt; /// Demonstrate a function *generic* over any type. /// /// This uses a cross-language convention for generics, where `T` represents the /// generic *type*. If we have more than one generic type, it's traditional to /// represent it with following letters, after `T`: `U`, `V`, `W`, etc. (If you /// have four *different* generic parameters, I'm probably going to look askance /// at your API design, though, to be honest.) pub fn a_generic(_t: T) { println!("The function works, but I can't actually do anything with the `_t`."); println!("Why? Well, because it might not have the `Display` or `Debug` traits implemented."); println!("What's a trait? I'm so glad you asked."); } /// Demonstrate a function with a *trait bound on a generic*. pub fn a_generic_printable(t: T) { println!("This function can actually debug-print `t`, whatever it may be."); println!("So: {:?}", t); } /// This is `Option`, but using Haskell's names instead. pub enum Maybe { Nothing, Just(T), } /// A simple type to illustrate trait implementation. pub struct SimpleType { a: String, b: i32, } /// Define the display format for the `SimpleType`. /// /// Note that this works because `String` and `i32` both already have display /// types implemented themselves! impl fmt::Display for SimpleType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "string: {} | integer: {}", self.a, self.b) } } /// This is just a container which can hold any two types. /// /// These types can even be the same, but they don't have to be. Moreover, they /// can be generic types themselves; as you can see in the tests below, you can /// use built-in or user-created generic types within this generic type. pub struct GenericContainer { pub t: T, pub u: U, } /// Show that the generics work! #[cfg(test)] mod tests { use super::*; /// An example struct for the tests. #[derive(Debug)] struct TestPoint { x: f32, y: i32, } /// An example enum for the tests. #[derive(Debug)] enum TestEnum { Nope, SomePointTuple(f32, i32), /// Any tuple type SomeAnonStruct { x: f32, y: i32, }, /// Functionally just like `TestPoint` SomePointStruct(TestPoint), // Embed an actual `TestPoint` } /// All of these tests will pass. #[test] fn test_generic_fn() { a_generic(1); a_generic(()); a_generic((1, 2)); a_generic(TestPoint { x: 14.0, y: 12 }); a_generic(TestEnum::Nope); a_generic(TestEnum::SomePointTuple(13.0, 10)); a_generic(TestEnum::SomeAnonStruct { x: 24.3, y: 10 }); a_generic(TestEnum::SomePointStruct(TestPoint { x: 1.2, y: 3 })); } /// So will all of these. #[test] fn test_generic_fn_with_debug_print() { a_generic_printable(1); a_generic_printable(()); a_generic_printable((1, 2)); a_generic_printable(TestPoint { x: 14.0, y: 12 }); a_generic_printable(TestEnum::Nope); a_generic_printable(TestEnum::SomePointTuple(13.0, 10)); a_generic_printable(TestEnum::SomeAnonStruct { x: 24.3, y: 10 }); a_generic_printable(TestEnum::SomePointStruct(TestPoint { x: 1.2, y: 3 })); } #[test] fn test_generic_enum() { // `_nothing` must have its type specified because it can't be inferred // from the context. Generics can be type-inferred (see below), but as // with all types in Rust, when they can't be, you specify them. let _nothing: Maybe = Maybe::Nothing; let _just_25 = Maybe::Just(25); let _just_str = Maybe::Just("whoa"); let _just_slice = Maybe::Just([1, 2, 3]); // Here we have a generic enum, wrapping a generic container, `Vec`! let _just_vec = Maybe::Just(vec![1, 2, 3]); // Things could get complicated if we need to define a `Maybe::Nothing` // for a `Vec`: we need to specify the `Vec` type as well: let _no_vec: Maybe> = Maybe::Nothing; // Normally that woudn't be a problem, because it would be inferred by // the context, with a pattern match: let pattern = false; let _maybe_vec = match pattern { false => Maybe::Nothing, true => Maybe::Just(vec![1, 2, 3]), }; } #[test] fn test_generic_struct() { // The generic container can contain "normal" (non-generic) types. let _container = GenericContainer { t: 14.0, u: "alpha", }; // But it can also contain generic types, like `Vec` or the `Maybe` // type we defined above. let _another = GenericContainer { t: vec![1, 2, 3], u: Maybe::Just("a string"), }; } #[test] fn test_impl_display() { let simple = SimpleType { a: "some string".to_string(), b: 4096, }; println!("simple is {}", simple); } } ================================================ FILE: src/e009.rs ================================================ //! Composing a Rustic tune //! //! - **Date:** 2016-01-09 //! - **Subject:** Getting into the nitty-gritty with Rust's traits. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e009.mp3 //! //! //! //! //! Notes //! ----- //! Last time, we looked at generics and traits at a high level. This time, we //! dig deeper on traits, looking specifically at `std::iter::Iterator` as an //! example of a powerful trait that can be composed across types, and then at //! how we might compose multiple traits on a single type. //! //! We also talk about the syntax for traits, the use of marker traits, some of //! the things you *can't* presently do with traits, and even just a smidge //! about the *future* of traits in Rust. All that in less than 20 minutes! //! //! You'll find today's [source example][src] fairly interesting, I think: it's //! just one type, but it uses almost every concept discussed on the show today! //! //! [src]: /src/show_notes/e009.rs.html //! //! //! Links //! ----- //! //! - Nick Cameron: ["Thoughts on Rust in 2016"][l1] //! - ["Upcoming breakage starting in Rust 1.7, from RFCs 1214 and 136"][l2] //! + [RFC 1214: Clarify (and improve) rules for projections and well-formedness][l3] //! + [RFC 136: Ban private items in public APIs][l4] //! - The Rust Book: //! + [Traits][l5] //! + [Trait objects][l6] (dynamic dispatch) //! - The Rust reference: //! + [`std::iter`][l7] and [`std::iter::Iterator`][l8] //! + [`Add`][l9] //! + [`Drop`][l10] //! + [`PartialEq`][l11] and [`Eq`][l12] //! + [`PartialOrd`][l13] and [`Ord`][l14] //! + [Special traits][l5] //! + [Trait objects][l16] //! - [RFC: impl specialization][l17] //! + Aaron Turon: ["Specialize to reuse"][l18] //! //! [l1]: http://www.ncameron.org/blog/my-thoughts-on-rust-in-2016/ //! [l2]: https://users.rust-lang.org/t/upcoming-breakage-starting-in-rust-1-7-from-rfcs-1214-and-136/4207 //! [l3]: https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md //! [l4]: https://github.com/rust-lang/rfcs/blob/master/text/0136-no-privates-in-public.md //! [l5]: https://doc.rust-lang.org/book/traits.html //! [l6]: https://doc.rust-lang.org/book/trait-objects.html //! [l7]: https://doc.rust-lang.org/std/iter/index.html //! [l8]: https://doc.rust-lang.org/std/iter/trait.Iterator.html //! [l9]: https://doc.rust-lang.org/std/ops/trait.Add.html //! [l10]: https://doc.rust-lang.org/std/ops/trait.Drop.html //! [l11]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html //! [l12]: https://doc.rust-lang.org/std/cmp/trait.Eq.html //! [l13]: https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html //! [l14]: https://doc.rust-lang.org/std/cmp/trait.Ord.html //! [l15]: https://doc.rust-lang.org/reference.html#special-traits //! [l16]: https://doc.rust-lang.org/reference.html#trait-objects //! [l17]: https://github.com/rust-lang/rfcs/pull/1210 //! [l18]: https://aturon.github.io/blog/2015/09/18/reuse/ //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Chris Palmer //! - [Derek Morr][s3] //! - Hamza Sheikh //! - Luca Schmid //! - Micael Bergeron //! - Ralph Giles ("rillian") //! - reddraggone9 //! - [William Roe][s9] //! //! [s3]: https://twitter.com/derekmorr //! [s9]: http://willroe.me //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! //! Follow //! ------ //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) use std::fmt; use std::ops; /// Define a simple struct on which to implement `Iterator`... and more! /// /// Pull in the `Clone` and `Copy` traits so that we can create copies cheaply /// with `into_iter`. Derive `Debug` so error printing works. Derive `PartialEq` /// so items can be compared! /// /// Look at all those default implementations we get for free! #[derive(Clone, Copy, Debug, PartialEq)] pub struct DoubleAndOne { /// A value to double and add one to on every `next()` call. pub value: i64, } impl DoubleAndOne { /// Start with 0. pub fn the_usual() -> DoubleAndOne { DoubleAndOne { value: 0 } } } /// Define a simple trait so we can see how it works. /// /// Note that its `a_default_print()` method becomes available automatically for /// `DoubleAndOne` when we `impl ASimpleTrait for DoubleAndOne` below. pub trait ASimpleTrait { /// Have the item return an integer. fn get_some_integer(&self) -> i64; /// Have the item print and then return some string. fn a_default_print(&self) -> &str { let msg = "This is implemented already!"; println!("{}", msg); msg } } impl ASimpleTrait for DoubleAndOne { fn get_some_integer(&self) -> i64 { self.value } } impl fmt::Display for DoubleAndOne { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "DoubleAndOne.value = {}", self.value) } } impl Iterator for DoubleAndOne { /// Define the required `Item` as being the the struct itself. type Item = DoubleAndOne; fn next(&mut self) -> Option { self.value = self.value * 2 + 1; Some(DoubleAndOne { value: self.value }) } } impl ops::Add for DoubleAndOne { type Output = DoubleAndOne; fn add(self, rhs: DoubleAndOne) -> DoubleAndOne { DoubleAndOne { value: self.value + rhs.value, } } } /// Demonstrate using a for loop over an (infinite!) iterator. pub fn demonstrate_for() { let mut printed = 0; let max_to_print = 10; let d = DoubleAndOne::the_usual(); for item in d { println!("{}", item); printed += 1; if printed > max_to_print { break; } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_a_simple_trait() { let d = DoubleAndOne { value: 24 }; // We have the trait function we implemented. assert_eq!(d.get_some_integer(), 24); // We also have the trait function we *didn't* implement. assert_eq!(d.a_default_print(), "This is implemented already!"); } #[test] fn test_iterator() { let mut d = DoubleAndOne::the_usual(); assert_eq!(d.next(), Some(DoubleAndOne { value: 1 })); assert_eq!(d.next(), Some(DoubleAndOne { value: 3 })); assert_eq!(d.next(), Some(DoubleAndOne { value: 7 })); assert_eq!(d.next(), Some(DoubleAndOne { value: 15 })); assert_eq!(d.next(), Some(DoubleAndOne { value: 31 })); assert_eq!(d.next(), Some(DoubleAndOne { value: 63 })); } #[test] fn test_add() { let d = DoubleAndOne { value: 10 }; let e = DoubleAndOne { value: 12 }; assert_eq!(d + e, DoubleAndOne { value: 22 }); } #[test] fn test_together() { let d = DoubleAndOne { value: 42 }; let e = d.into_iter().next().unwrap(); assert_eq!(d + e, DoubleAndOne { value: 127 }); } } ================================================ FILE: src/e010.rs ================================================ //! Macros rule! //! //! - **Date:** 2016-01-18 //! - **Subject:** Using Rust's macro system, its limitations, and its future. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e010.mp3 //! //! //! //! //! Notes //! ----- //! //! Because of the way macros are exported---before name resolution on crates //! occurs---the documentation for the macros defined in the source for this //! episode occurs in the [**Macros** section of the `show_notes` crate][n1] //! documentation, rather than within the documentation for this module. (See //! the Rust Book discussion of [documenting macros][n2] for details.) Even so, //! the [source][n3] is still in this module; see the [implementations][n4] for //! details. //! //! [n1]: https://www.newrustacean.com/show_notes/#macros //! [n2]: http://doc.rust-lang.org/stable/book/documentation.html#documenting-macros //! [n3]: https://www.newrustacean.com/src/show_notes/e009.rs.html //! [n4]: https://www.newrustacean.com/src/show_notes/e010.rs.html#101 //! //! Links //! ----- //! - Julia Evans: ["Why I (Heart) Rust"][l1] //! - Steve Klabnik: ["IntermezzOS"][l2] (a small teaching OS built in Rust) //! - [Rust book: Macros][l3] //! - [Rust by Example: Macros][l4] //! - [Rust reference: Macros][l5] //! - ["Macro by Example"][l6] (original paper) //! - Nick Cameron: //! + [Macros][l7] //! + Macros in Rust //! * [Part 1: `macro_rules!`][l8] //! * [Part 2: procedural macros][l9] //! * [Part 3: hygiene][l10] //! * [Part 4: scoping and import/export][l11] //! * [Part 5: current problems and possible solutions][l12] //! * [Part 6: more issues with `macro_rules!`][l13] //! + [`concat_idents` and macros in ident positions][l14] //! + [Macro plans, overview][l15] //! + [Macro hygiene in all its guises and variations][l16] //! + [Sets of scopes macro hygiene][l17] //! + [Macro plans: syntax][l18] //! + [Procedural macros, framework][l19] //! //! [l1]: https://speakerdeck.com/jvns/why-i-rust //! [l2]: https://intermezzos.github.io/ //! [l3]: https://doc.rust-lang.org/book/macros.html //! [l4]: http://rustbyexample.com/macros.html //! [l5]: https://doc.rust-lang.org/reference/macros.html //! [l6]: https://www.cs.indiana.edu/ftp/techreports/TR206.pdf //! [l7]: http://www.ncameron.org/blog/macros/ //! [l8]: http://ncameron.org/blog/macros-in-rust-pt1/ //! [l9]: http://www.ncameron.org/blog/macros-in-rust-pt2/ //! [l10]: http://www.ncameron.org/blog/macros-in-rust-pt3/ //! [l11]: http://www.ncameron.org/blog/macros-in-rust-pt4/ //! [l12]: http://www.ncameron.org/blog/macros-in-rust-pt5/ //! [l13]: http://www.ncameron.org/blog/macros-pt6-more-issues/ //! [l14]: http://www.ncameron.org/blog/untitledconcat_idents-and-macros-in-ident-position/ //! [l15]: http://www.ncameron.org/blog/macro-plans-overview/ //! [l16]: http://www.ncameron.org/blog/macro-hygiene-in-all-its-guises-and-variations/ //! [l17]: http://www.ncameron.org/blog/sets-of-scopes-macro-hygiene/ //! [l18]: http://www.ncameron.org/blog/macro-plans-syntax/ //! [l19]: http://www.ncameron.org/blog/procedural-macros-framework/ //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Chris Palmer //! - [Derek Morr][s3] //! - Hamza Sheikh //! - Luca Schmid //! - Micael Bergeron //! - Ralph Giles ("rillian") //! - reddraggone9 //! - [William Roe][s9] //! //! [s3]: https://twitter.com/derekmorr //! [s9]: http://willroe.me //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! //! Follow //! ------ //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + App.net: [@newrustacean](https://alpha.app.net/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! + App.net: [@chriskrycho](https://alpha.app.net/chriskrycho) /// Define a macro like `try!` but which works in the context of `main()`. /// /// [`try!`][try] takes a `Result` and, if it is `Ok`, supplies the `T` /// value, or if it is `Err` returns the error from the function. However, /// since `main` has a void tuple `()` return type, you cannot use `try!` in /// `main()`. This `main_try!` macro instead debug-prints the error and returns. /// /// [try]: https://doc.rust-lang.org/std/macro.try!.html /// /// ```rust /// # #[macro_use] extern crate show_notes; /// # fn main() { /// // Alias `Result` for brevity. /// type LocalResult = Result; /// /// let an_ok: LocalResult = Ok(10); /// let ok_val = main_try!(an_ok); /// assert_eq!(ok_val, 10); /// /// // We try to assign to another val, but it's an error, so we return. /// let an_err: LocalResult = Err("Alas, this is a failure."); /// let err_val = main_try!(an_err); // Prints `Alas, this is a failure.` /// // We'll never get here. If we did, the doctest would fail. /// assert!(false); /// # } /// ``` #[macro_export] macro_rules! main_try { ($e:expr) => { match $e { std::result::Result::Ok(val) => val, std::result::Result::Err(err) => { println!("{:?}", err); return; } } }; } /// Define an ident macro to show how they can capture different *syntax*. /// /// Whereas `main_try!` captured *expressions*, `print_ident_name!` captures /// *identifiers*. If you try to pass in an expression, it simply won't work. /// So, if you tried to do any of these, it won't compile: /// /// ```rust,ignore /// # #[macro_use] extern crate show_notes; /// # fn main() { /// print_ident_name!(()); /// print_ident_name!(42); /// print_ident_name!(if true { println!("Neato!"); } else { println!("Sads!"); }); /// # } /// ``` /// /// Instead, it will complain that it expected an identifier, and you handed it /// something else. /// /// On the other hand, this works just fine: /// /// ```rust /// # #[macro_use] extern crate show_notes; /// # fn main() { /// let _x = 0; /// print_ident_name!(_x); // "The ident's name was: _x" /// # } /// ``` /// /// In this case, the implementation uses two other macros: `format!` and /// `stringify!`, to accomplish its work. This highlights the reality that /// macros can use any other language machinery, including other macros. #[macro_export] macro_rules! print_ident_name { ($id:ident) => { format!("The ident's name was: {}", stringify!($id)) }; } /// Trivial alias for Result for convenience. pub type TryResult = Result; /// Demonstrate how `try!` works in practice. // Note: allows deprecated because the point here was to show the old `try!` // macros from *before* we had `?`. pub fn demonstrate_try(tr: TryResult) -> TryResult { // If the caller passes in an error, this returns that error. #[allow(deprecated)] let val = r#try!(tr); // Thus, if `tr` was `Err`, we'll never get here. If it's an `Ok`, `val` has // the value, so we can return it slightly modified to show that that's what // actually happened. Ok(val + 1) } #[cfg(test)] mod tests { use super::*; #[test] fn test_demonstrate_try() { assert_eq!(demonstrate_try(Ok(14)), Ok(15)); assert_eq!(demonstrate_try(Err("WHAT")), Err("WHAT")); } #[test] fn test_print_ident_name() { // We can operate on any identifier. Variables: let _x = 42; assert_eq!(print_ident_name!(_x), format!("The ident's name was: _x")); // Functions: assert_eq!( print_ident_name!(demonstrate_try), format!("The ident's name was: demonstrate_try") ); // Types: assert_eq!( print_ident_name!(TryResult), format!("The ident's name was: TryResult") ); // Even macros! assert_eq!( print_ident_name!(print_ident_name), format!("The ident's name was: print_ident_name") ); } } ================================================ FILE: src/e011.rs ================================================ //! Once upon a type //! //! - **Date:** March 6, 2016 //! - **Subject:** Type systems: strong vs. weak, dynamic vs. static, and //! degrees of expressivity. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e011.mp3 //! //! //! //! //! Notes //! ----- //! //! Talking about type systems! A broad and wide-ranging discussion about type //! systems in general, with specific examples from languages like PHP, //! JavaScript, Python, C, C++, Java, C♯, Haskell, and Rust! //! //! - What is a type system? //! - What are the kinds of things we get out of type systems? //! - What are the tradeoffs with different type systems? //! - What is Rust's type system like? //! - What is especially attractive about Rust's type system? //! //! A comment on the C integer/character string addition example: what's //! actually happening there is that the character string is an array "under the //! covers," and as such has an address. C silently switches to using the memory //! address, which is of course just an integer, when you try to add the two //! together. As I said on the show: the result is nonsense (unless you're using //! this as a way of operating on memory addresses), but it's compileable //! nonsense. In a stricter and stronger type system, memory addresses and //! normal numbers shouldn't be addable! //! //! //! Links //! ----- //! //! - [Rust 1.7 released][l1] //! + [`HashMap` changes][l2] //! - [Introduction to Type Theory][l3] //! - [Visualizing Rust's type-system][l4] //! - [The Many Kinds of Code Reuse in Rust][l5] //! //! [l1]: http://blog.rust-lang.org/2016/03/02/Rust-1.7.html //! [l2]: http://blog.rust-lang.org/2016/03/02/Rust-1.7.html#library-stabilizations //! [l3]: http://www.cs.ru.nl/~herman/PUBS/IntroTT-improved.pdf //! [l4]: https://jadpole.github.io/rust/type-system //! [l5]: http://cglab.ca/~abeinges/blah/rust-reuse-and-recycle/ //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Chris Palmer //! - [Derek Morr][s3] //! - Hamza Sheikh //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - Pascal //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - reddraggone9 //! - Ryan Ollos //! - [William Roe][s11] //! //! [s3]: https://twitter.com/derekmorr //! [s11]: http://willroe.me //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) use std::fmt; /// Is the thing "expressive", whatever that means? pub enum Expressive { Ridiculously, PrettyDarn, Fairly, SortOf, Barely, NotEvenALittle, } impl fmt::Display for Expressive { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let description = match *self { Expressive::Ridiculously => "ridiculously", Expressive::PrettyDarn => "pretty darn", Expressive::Fairly => "fairly", Expressive::SortOf => "sort of", Expressive::Barely => "barely", Expressive::NotEvenALittle => "not even a little", }; write!(f, "{} expressive", description) } } /// Is the thing *strong*? pub enum Strong { Indeed, ABit, NotEspecially, NopeNopeNope, } impl fmt::Display for Strong { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let description = match *self { Strong::Indeed => "strong indeed", Strong::ABit => "a bit strong", Strong::NotEspecially => "not especially strong", Strong::NopeNopeNope => "strong? NOPE NOPE NOPE", }; write!(f, "{}", description) } } /// Is the thing statically known? pub enum StaticallyKnown { Yeah, Nope, } impl fmt::Display for StaticallyKnown { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let description = match *self { StaticallyKnown::Yeah => "it's totally known at compile time", StaticallyKnown::Nope => "we don't know anything about it until run time", }; write!(f, "{}", description) } } /// Look, we composed those enums into another type. How... droll. pub struct TypeSystem { name: String, expressive: Expressive, strong: Strong, statically_known: StaticallyKnown, } impl TypeSystem { pub fn builder( name: &str, expressive: Expressive, strong: Strong, statically_known: StaticallyKnown, ) -> TypeSystem { TypeSystem { name: name.to_string(), expressive, strong, statically_known, } } } /// An incredibly contrived function which just shows enums at work. /// /// I wanted there to be *some* sample code this episode, you know? This one /// just assembles the types into a vector and prints them all. It does, /// however, let us refresh ourselves on a bunch of other concepts we've covered /// on the show---pretty much everything but generics makes an appearance in /// some way in this module. pub fn describe_type_systems() { let js = TypeSystem::builder( "ECMAScript", Expressive::Fairly, Strong::NopeNopeNope, StaticallyKnown::Nope, ); let php = TypeSystem::builder( "PHP", Expressive::Barely, Strong::NopeNopeNope, StaticallyKnown::Nope, ); let c = TypeSystem::builder( "C", Expressive::Barely, Strong::NotEspecially, StaticallyKnown::Yeah, ); let cpp = TypeSystem::builder( "C++", Expressive::SortOf, Strong::ABit, StaticallyKnown::Yeah, ); let java = TypeSystem::builder( "Java", Expressive::SortOf, Strong::ABit, StaticallyKnown::Yeah, ); let csharp = TypeSystem::builder( "C♯", Expressive::Fairly, Strong::Indeed, StaticallyKnown::Yeah, ); let swift = TypeSystem::builder( "Swift", Expressive::PrettyDarn, Strong::Indeed, StaticallyKnown::Yeah, ); let rust = TypeSystem::builder( "Rust", Expressive::PrettyDarn, Strong::Indeed, StaticallyKnown::Yeah, ); let haskell = TypeSystem::builder( "Haskell", Expressive::Ridiculously, Strong::Indeed, StaticallyKnown::Yeah, ); let langs = vec![js, php, c, cpp, java, csharp, swift, rust, haskell]; for lang in langs { println!( "{language} is {expressive}, {strong}, and {statically_known}", language = lang.name, expressive = lang.expressive, strong = lang.strong, statically_known = lang.statically_known ); } } ================================================ FILE: src/e012.rs ================================================ //! I'm not familiar with that expression //! //! - **Date:** March 21, 2016 //! - **Subject:** What it means to be an expression-oriented language, and //! how that works out in Rust. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e012.mp3 //! //! //! //! //! Notes //! ----- //! //! Rust is an *expression-oriented* language. What does that mean, and how does //! it play out in Rust? We look at `if` and `match` blocks, discuss looping //! constructs, and examine functions, and then widen out to discuss how having //! an expression-oriented language can change the way we think about //! programming. //! //! //! Links //! ----- //! //! - [Redox][l1] //! - [Servo alpha announcement][l2] //! - [WebRender][l3] //! - [Wired article on Dropbox][l4] //! - Rust documentation on expression-oriented-ness: //! + [Rust Book][l5] //! + [Rust by Example][l6] //! + [Rust Reference][l7] //! - [Removing Rust ternary][l8] //! - [Digits of pi necessary for astronavigation][l9] //! //! [l1]: http://www.redox-os.org //! [l2]: https://groups.google.com/forum/#!topic/mozilla.dev.servo/dcrNW6389g4 //! [l3]: https://air.mozilla.org/bay-area-rust-meetup-february-2016/#@25m50s //! [l4]: http://www.wired.com/2016/03/epic-story-dropboxs-exodus-amazon-cloud-empire/ //! [l5]: https://doc.rust-lang.org/book/functions.html#expressions-vs-statements //! [l6]: http://rustbyexample.com/expression.html //! [l7]: https://doc.rust-lang.org/reference.html#statements-and-expressions //! [l8]: https://github.com/rust-lang/rust/issues/1698 //! [l9]: http://www.jpl.nasa.gov/edu/news/2016/3/16/how-many-decimals-of-pi-do-we-really-need/ //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Chris Palmer //! - [Derek Morr][s3] //! - Hamza Sheikh //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - Pascal //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - reddraggone9 //! - Ryan Ollos //! - [William Roe][s11] //! //! [s3]: https://twitter.com/derekmorr //! [s11]: http://willroe.me //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) use std::f64; /// Functions are expressions, and so are their contents. /// /// This is the foundation of the other items in this modules, because it is in /// using functions as expressions that we'll be able to demonstrate clearly /// that if blocks and match blocks are *also* expressions. /// /// Note that we can see several things going on in the body of this function: /// /// 1. The items within the function are expressions. /// 2. The function *returns* the value of the final expression in the function /// body. But a better way to think about it is to see the function as having /// that value *itself*, because... /// 3. The function itself *is* an expression, which is evaluated to have the /// value of that final expression! pub fn functions_are_expressions() -> i32 { // We can do as many things inside as statements as we like. Note that these // statements are actually still expressions, whose value is the empty tuple // `()`, sometimes called the "unit type". let a = 14; let b = 12; // Now that we're done, we can just return the desired value by making the // final line of the function *just* an expression, not a statement, so that // the evaluated value is not `()` but that of the expression (so: 26)! a + b } /// Like functions, if blocks are expressions. /// /// This function simple doubly demonstrates this, by showing an assignment from /// one evaluated expression, and by returning the result of another directly. pub fn if_blocks_are_expressions() -> f64 { // note the terminal boolean expressions, unterminated! let a_bool = if "quuxy".len() > 3 { print!("Totally a long word"); true } else { print!("Not at all long"); false }; // This wouldn't work: the compiler would report mismatched types as the // values of the `if` and `else` expressions. // let mismatched_types = if true { // 42 // } else { // "quuxy" // }; // Here, we are returning the result of this expression, not only from the // if/else block, but from the whole function, because *this* expression is // the final, unterminated expression of a function, as above! if a_bool { 42.0 } else { f64::consts::PI } } enum ThreeTypes { _First, Second, _Third, } /// Match blocks are also expressions. /// /// This particular example demonstrates both local binding and returning a /// match expression's value as the return value from the entire function. pub fn match_blocks_are_expressions() -> String { let a_three_type = ThreeTypes::Second; let x = match a_three_type { ThreeTypes::_First => 42, ThreeTypes::Second => i64::min_value(), ThreeTypes::_Third => i64::max_value(), }; match x { 0..=100 => "Less than 100".to_string(), _ => "Less than 0, or more than 100".to_string(), } } /// Block blocks are also expressions! /// /// In the trivial example below, we have a situation that doesn't come up /// especially often (and certainly wouldn't in this trivial way), but is a real /// option and is handy when you need it. You can create arbitrary blocks pub fn ordinary_blocks_are_expressions() -> i32 { let a_block_result = { println!("You can evaluate *any* block, see?"); println!("And the final expression is still returned."); // a_block_result will be 14 14 }; // And that's what we'll return from the function, from this utterly // pointless block! (These kinds of things aren't always pointless, though.) { a_block_result } } ================================================ FILE: src/e013.rs ================================================ /*! Staying alive - **Date:** April 4, 2016 - **Subject:** Reasoning about and using lifetimes in Rust (and why we need them) - [**Audio**][mp3] [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e013.mp3 Notes ----- Lifetimes are our way of reasoning about how long a given piece of data is available and safe to use in Rust. The reason we don't have the dangling pointer problem is that we *do* have lifetimes instead. They're not magic, they're just a bit of semantics and syntax that let us specify the rules for how long any given item lives, and how long references to data must be valid. Links ----- - [Diesel][l1] + [Tutorial][l2] + [API docs][l3] - [Mio, an I/O library][l4] + [Getting Started][l5] + [API Docs][l6] [l1]: http://diesel.rs [l2]: http://diesel.rs/guides/getting-started/ [l3]: http://docs.diesel.rs/diesel/index.html [l4]: https://github.com/carllerche/mio [l5]: https://github.com/carllerche/mio/blob/getting-started/doc/getting-started.md [l6]: http://rustdoc.s3-website-us-east-1.amazonaws.com/mio/master/mio/ Sponsors -------- - Aleksey Pirogov - [Chris Palmer] - [Derek Morr] - Hamza Sheikh - Lachlan Collins - Leif Arne Storset - Luca Schmid - Micael Bergeron - [Pascal Hertleif] - Ralph Giles ("rillian") - Ralph "FriarTech" Loizzo - reddraggone9 - Ryan Ollos - Vesa Kaihlavirta - [William Roe] [Chris Palmer]: http://red-oxide.org/ [Derek Morr]: https://twitter.com/derekmorr [Pascal Hertleif]: https://pascalhertleif.de/ [William Roe]: http://willroe.me (Thanks to the couple people donating who opted out of the reward tier, as well. You know who you are!) ### Become a sponsor - Patreon - [Venmo](https://venmo.com/chriskrycho) - [Dwolla](https://www.dwolla.com/hub/chriskrycho) - [Cash.me](https://cash.me/$chriskrycho) Contact ------- - New Rustacean: + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) - Chris Krycho + GitHub: [chriskrycho](https://github.com/chriskrycho) + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) Examples -------- Here's an example of a function which won't actually compile. The reason is: the item we're trying to return a reference to (`cast`) is created inside the block and therefore goes out of scope at the end of the block. Putting a lifetime declaration on it is irrelevant! ```rust,ignore fn bad_ref_in_ref_out<'a>(num_ref: &'a i64) -> &'a f64 { // We can create a local binding using the input. let cast = *num_ref as f64; // We can even create a reference to it. let cast_ref: &'a f64 = &cast; // What we can't do is return the reference, because `cast` itself will go // out of scope on the next line and be cleaned up. cast_ref } ``` */ /** An individual person defined in a way that includes a *reference* type. The lifetime of the reference member, `name`, needs to match the lifetime of the `Person` itself. We'd end up with a pretty weird scenario otherwise! Note that the lifetimes of the members match the lifetime declared for the type itself, so the references must live *at least as long* as the instance of the type to which they're attached. */ pub struct Individual<'a> { /// The person's name, as a string *reference*. pub name: &'a str, /// Just in case we're talking about a character from Genesis pub age: i16, } // TODO: over the next week, fill this out! /// Note that the implementation block *also* has the lifetimes declared. impl<'a> Individual<'a> {} /** A reference to a number, either integral or floating-point. Goofy, yes. The same basic rules apply to enumerated types as to struct types. If you don't include the lifetime on the type itself, the compiler won't let it pass when you try to use the enum. As in the `struct` example, the lifetimes of both items match the lifetime declared on the type itself. */ pub enum NumericReference<'a> { IntRef(&'a i64), FloatRef(&'a f64), } // TODO: over the next week, fill this out! impl<'a> NumericReference<'a> {} /** Get a(n optional) sub-slice of a slice. Note that here we have a reference coming both directions, and therefore lifetimes on both the input and the output. These can be elided, but are left here for illustrative purposes! What we're doing here is returning a *reference* to everything but the "head" of the slice. Since the slice might be empty, or might have only one element, we treat this as an optional. */ #[allow(clippy::needless_lifetimes)] pub fn refs_all_around<'a>(input: &'a [i32]) -> Option<&'a [i32]> { if input.len() > 2 { Some(&input[1..]) } else { None } } #[cfg(test)] mod tests { use super::*; #[test] fn test_refs_all_around() { let the_thing = [1, 2, 3, 4]; let result = refs_all_around(&the_thing); assert_eq!(the_thing[1..], *result.unwrap()); } } ================================================ FILE: src/e014.rs ================================================ //! Stringing things along //! //! - **Date:** April 24, 2016 //! - **Subject:** `Strings` `&str`s and `Vec`s and slices (and Unicode) -- //! oh, my! //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e014.mp3 //! //! //! //! //! Notes //! ----- //! //! This episode, I take a deep dive on strings in Rust, looking at the //! differences between `String` and `&str`, discussing Unicode a bit, and then //! expanding the discussion to think about how these types relate to the types //! they're built on (like `Vec`). //! //! ### Corrigenda //! //! Listener Nev pointed out to me that I got it wrong when describing how //! `&str` data is stored. It is *not* stack-allocated, but rather goes in the //! [data segment]. I should have said *statically*-allocated, not //! *stack*-allocated. Thanks to Nev for the correction! //! //! [data segment]: https://en.wikipedia.org/wiki/Data_segment //! //! //! Links //! ----- //! //! - Strings: //! + [The Rust Book] //! + [Rust by Example] //! + `str` docs: //! * [module][strmod] //! * [primitive type] //! + `String` //! * [module][stringmod] //! * [type definition] //! - Dereferencing //! + [coercions] //! + [`std::ops::Deref`] //! //! [The Rust Book]: https://doc.rust-lang.org/book/strings.html //! [Rust by Example]: http://rustbyexample.com/std/str.html //! [strmod]: http://doc.rust-lang.org/std/str/ //! [primitive type]: http://doc.rust-lang.org/std/primitive.str.html //! [stringmod]: http://doc.rust-lang.org/std/string/index.html //! [type definition]: http://doc.rust-lang.org/std/string/struct.String.html //! [coercions]: http://doc.rust-lang.org/book/deref-coercions.html //! [`std::ops::Deref`]: http://doc.rust-lang.org/std/ops/trait.Deref.html //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - [Chris Palmer] //! - [Derek Morr] //! - Hamza Sheikh //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - [Pascal Hertleif] //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - reddraggone9 //! - Ryan Ollos //! - Vesa Kaihlavirta //! - [William Roe] //! //! [Chris Palmer]: http://red-oxide.org/ //! [Derek Morr]: https://twitter.com/derekmorr //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) /// Get a string *slice*. Note the required lifetime specifier on the type! /// /// String slices are pointers to a given chunk of data. pub fn get_a_slice() -> &'static str { "this is a statically allocated slice" } /// Get a `String` instance. Note there's no lifetime. pub fn get_a_string() -> String { let mut a_string = String::new(); a_string += "this is a heap-allocated String"; a_string } /// It's easy enough to get a `String` from a `str`. pub fn show_from_behavior() -> String { String::from("any old slice will do") } /// Print a 🚀, just because we can. pub fn demonstrate_unicode() { println!("🚀"); } pub fn get_back_some_unicode(desc: &str) -> String { match desc { "rocket" => "🚀".to_string(), "hearts" => "💕".to_string(), _ => " ".to_string(), } } /// Get a `String` with a specified capacity. /// /// Strings are heap-allocated, so we can simply build them to hold a certain /// number of characters by default if we know how big they are, allowing them /// to expand later *if necessary*. pub fn get_a_string_with_capacity(capacity: usize) -> String { let mut string = String::with_capacity(capacity); string += "few"; string } /// Demonstrate dereferencing. (You'll want to read this example carefully.) /// /// Note that here we have two types which are empty of values, which makes the /// dereferencing operation quite straightforward. If the types had contents, /// this would be a bit more involved! /// /// Note as well that the dereference in this case recurses. This is a /// consequence of having the empty types---so it's not exactly recommended to /// do this in that case! (In fact, it's *usually*, though not always, pointless /// to do that.) pub mod demo_deref { use std::ops::Deref; /// A no-content struct to serve as the type to dereference from. pub struct Origin; /// A no-content struct to serve as the target to dereference to. pub struct DerefTarget; impl Deref for Origin { type Target = DerefTarget; // This is broken: that is the *point*. #[allow(unconditional_recursion)] fn deref(&self) -> &DerefTarget { self } } } #[cfg(test)] mod tests { use super::*; #[test] fn show_string_capacity() { let capacity: usize = 4; let mut the_str = get_a_string_with_capacity(capacity); assert_eq!(the_str.capacity(), capacity); the_str += "this is more than 4"; assert!(the_str.capacity() > capacity); } } ================================================ FILE: src/e015.rs ================================================ //! Not dumb pointers. //! //! - **Date:** June 17, 2016 //! - **Subject:** `Box`, `String`, `Vec`, `Rc`, and `Arc` have this in //! common: they're not dumb. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e015.mp3 //! //! //! //! //! Notes //! ----- //! //! This episode, we take a close look at smart pointer types---from a few we've //! already talked about, like `Box`, `Vec`, and `String`, to some new ones, //! like `Rc` and `Arc`. //! //! - What smart pointers are, and what makes them 'smart'. //! - Why we want or need smart pointers. //! - A bit about `Box`. //! - A lot more about `Rc` and `Arc`. //! //! ***Note:*** The examples below are in-progress: the `Rc` example is complete //! but not fully documented, and there's no examples yet for `Arc`---but there //! will be! I expect to finish them over the course of this weekend, but I //! wanted to go ahead and get the episode out! //! //! ### Further reading //! //! - _The Rust Programming Language_: //! + [The Stack and the Heap] //! + [Choosing Your Guarantees] -- see especially the sections on //! `Rc` and `Arc`. //! - Rust by Example: [17.1: Box, stack, and heap][rbe] //! - API docs: //! + [`std::boxed`] //! + [`std::rc`] //! + [`stc::sync::Arc`] //! //! Links //! ----- //! //! - [RustConf] //! - [Rust Belt Rust Conference] //! + [sessions] //! - [Rusty Radio] //! + [feed] //! - [Rust Exercism track] //! + [All exercism language tracks] //! - [RFC 1636: Require documentation for all new features.][RFC1636] (Note: //! I misspoke on the episode and said this was at rust-lang.org; it's not! //! It's on GitHub, wtih the rest of the RFCs, of course.) //! //! [RustConf]: http://rustconf.com //! [Rust Belt Rust Conference]: http://www.rust-belt-rust.com //! [sessions]: http://www.rust-belt-rust.com/sessions/ //! [Rusty Radio]: https://soundcloud.com/posix4e/sets/rustyradio //! [feed]: http://feeds.soundcloud.com/users/soundcloud:users:1287419/sounds.rss //! [Rust Exercism track]: http://exercism.io/languages/rust //! [All exercism language tracks]: http://exercism.io/languages //! [RFC1636]: https://github.com/rust-lang/rfcs/pull/1636 //! [The Stack and the Heap]: https://doc.rust-lang.org/book/the-stack-and-the-heap.html //! [Choosing Your Guarantees]: https://doc.rust-lang.org/book/choosing-your-guarantees.html //! [rbe]: http://rustbyexample.com/std/box.html //! [`std::boxed`]: https://doc.rust-lang.org/std/boxed/index.html //! [`std::rc`]: https://doc.rust-lang.org/std/rc/index.html //! [`stc::sync::Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - [Chris Palmer] //! - [Daniel Collin] //! - [Derek Morr] //! - Doug Reeves //! - Hamza Sheikh //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - [Pascal Hertleif] //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - Raph Levien //! - reddraggone9 //! - Ryan Ollos //! - Vesa Kaihlavirta //! - [William Roe] //! //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) //! //! //! Examples //! -------- //! //! The most basic examples of smart pointers involve the `Box` type, which //! we've talked about before. Assume we had a type `Foo` which took a string in //! its constructor, and that we wanted to box it up. We would just write: //! //! ```rust,ignore //! let someFoo = Box::new(Foo::new("bar")); //! ``` //! //! It's also worth comparing the Rust code above with similar code in C++. //! Assume we have a `class` with the same name; using a smart pointer (in this //! case, `unique_ptr`, returned from `make_unique`) would give us this code: //! //! ```cpp //! const auto someFoo = std::make_unique("bar"); //! ``` //! //! Both examples declare a smart pointer named `someFoo` that points to an //! immutable/constant `Foo` and where the pointer itself is immutable/constant. //! However, note that the Rust code is briefer and (at least in my opinion) //! substantially clearer than the corresponding C++ code to express the same //! semantic content. //! //! I'm not including further comments on `Box` here in the docs, because we've //! covered it before and it's fairly straightforward. The rest of these //! materials focus entirely on `Rc` and `Arc`, as those are the most //! interesting bits from today's episode. use std::rc::{Rc, Weak}; // use std::sync::Arc; // TODO /// A trivial (and frankly rather silly) example for use with `Rc`. pub struct FileData { contents: String, } impl FileData { pub fn new(contents: &str) -> FileData { FileData { contents: contents.to_string(), } } } pub struct ASendableType {} /// Note that this function is *generic*: it will work for any type. pub fn print_rc_count(t: &Rc) { println!("Reference count: {:}", Rc::strong_count(t)); } /// Note that this function is not generic because it assumes `FileData`. fn print_rc_body(fd: &Rc) { println!("The contents are: {:}", fd.contents); } /// Demonstrate the basics of reference-counted types. (Read the source, Luke!) pub fn demonstrate_rc() { // Note that we have valid data here. let a_ref = get_wrapped_file_data(); print_rc_body(&a_ref); print_rc_count(&a_ref); // Just 1 let added_another_ref = a_ref.clone(); print_rc_count(&a_ref); // 2 // Create a block to show that we can get another copy. { let yet_another_ref = a_ref.clone(); print_rc_count(&yet_another_ref); // 3 print_rc_body(&yet_another_ref); // we can print the contents here. } // we've gone out of scope; `yet_another_ref` is deallocated here. print_rc_count(&a_ref); // 2 again drop(a_ref); // Remember, it doesn't matter which we drop! print_rc_count(&added_another_ref); // 1 print_rc_body(&added_another_ref); // valid // Most explicit form: let a_weak_ref: Weak = Rc::downgrade(&added_another_ref); // clone the weak ref. let _another_weak_ref = a_weak_ref.clone(); print_rc_count(&added_another_ref); // still 1. // Now we *move* the reference into the other function. let empty_weak = get_empty_weak(added_another_ref); match empty_weak.upgrade() { Some(fd) => println!("{:}", fd.contents), None => println!("Nothing to see here. We're done."), } } /// Note that this takes ownership of the data. pub fn get_empty_weak(fd: Rc) -> Weak { Rc::downgrade(&fd) } pub fn get_wrapped_file_data() -> Rc { let plain_data = FileData::new("This would really read from a file. And not be terrible."); // Both of these now have "strong" references to the type. Neither "trumps" // the other; whichever goes out of scope first will be deallocated, but // *without* affecting the other. let wrapped = Rc::new(plain_data); print_rc_count(&wrapped); let a_reference_to_it = wrapped.clone(); print_rc_count(&a_reference_to_it); a_reference_to_it } ================================================ FILE: src/e016.rs ================================================ //! `RefCell`s and code smells //! //! - **Date:** July 23, 2016 //! - **Subject:** Digging deeper on smart pointers and mutability with //! `Cell` and `RefCell`. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e016.mp3 //! //! //! //! //! Notes //! ----- //! //! What are the `Cell` and `RefCell` types, and when should we use them? //! //! Today, we follow up both the detailed discussion of smart pointers in //! [e015] and the closely related discussion in [Interview 2] with Raph Levien, //! and look at two types you need to have a good idea how to deal with if you //! want to use these smart pointer types more *ergonomically*---that is, how to //! use them without feeling like you're beating your head against a wall! //! //! [e015]: https://www.newrustacean.com/show_notes/e015/ //! [Interview 2]: https://www.newrustacean.com/show_notes/interview/_2/ //! //! The descriptions of the code below are minimal; see the inline comments in //! [the source][src] for the actual informative discussion. //! //! [src]: /src/show_notes/e016.rs.html //! //! //! ### A comment on the code samples //! //! Note that in several cases below we use `&[]` to borrow a reference to a //! slice, rather than requiring this to pass a reference to a `Vec` //! specifically. Making the first argument be of type //! `&Vec>` would also work, but would be more //! restrictive in what it could and couldn't accept. Since `Vec` implements //! [`Deref`] to automatically convert to slices, this works just fine, *and* is //! more general. This is how you should usually write function signatures which //! operate on reference to vectors (and likewise for other types which can //! dereference to slices). We'll talk about this more in a future episode! //! //! [`Deref`]: https://doc.rust-lang.org/1.10.0/std/ops/trait.Deref.html //! //! //! Links //! ----- //! //! - Rust 1.10 //! + [blog post] //! + [full release notes] //! + cdylib //! * RFC: [text] | [discussion] //! * [implementation] //! - [rustup 0.3.0 release] //! - [Integer32] \(Carol Nichols' and Jake Goulding's new Rust consultancy) //! + [announcement blog post] //! + [reddit discussion][reddit i32] //! - [IntelliJ Rust] //! + [reddit discussion][reddit ijr] //! - Tango: [source][Tango] | [talk] //! - `Cell` and `RefCell`: //! + [Cell Types] in _The Rust Programming Language_ //! + Standard library: //! * [`std::cell`] module docs (detailed explanation, complementary to the book) //! * [`Cell`] docs (at `std::cell::Cell`) //! * [`RefCell`] docs (at `stc::cell::RefCell`) //! //! [blog post]: https://blog.rust-lang.org/2016/07/07/Rust-1.10.html //! [full release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1100-2016-07-07 //! [text]: https://github.com/rust-lang/rfcs/blob/master/text/1510-rdylib.md //! [discussion]: https://github.com/rust-lang/rfcs/pull/1510 //! [implementation]: https://github.com/rust-lang/rust/pull/33553 //! [rustup 0.3.0 release]: https://internals.rust-lang.org/t/beta-testing-rustup-rs/3316/144 //! [Integer32]: http://www.integer32.com //! [announcement blog post]: http://www.integer32.com/2016/07/11/why-rust.html //! [reddit i32]: https://www.reddit.com/r/rust/comments/4sdncw/why_were_starting_a_rust_consultancy/ //! [IntelliJ Rust]: https://intellij-rust.github.io //! [reddit ijr]: https://www.reddit.com/r/rust/comments/4sbqaq/intellijrust_has_a_website_now/ //! [Tango]: https://github.com/pnkfelix/tango //! [talk]: https://skillsmatter.com/skillscasts/8372-tango-literate-programming-in-rust //! [Cell Types]: https://doc.rust-lang.org/book/choosing-your-guarantees.html#cell-types //! [`std::cell`]: https://doc.rust-lang.org/std/cell/index.html //! [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html //! [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - [Chris Palmer] //! - [Daniel Collin] //! - [Derek Morr] //! - Doug Reeves //! - Eric Fulmer //! - Hamza Sheikh //! - [Jakub "Limeth" Hlusička] //! - Keith Gray //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - Michael Clayton //! - [Pascal Hertleif] //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - Raph Levien //! - reddraggone9 //! - Ryan Ollos //! - Vesa Kaihlavirta //! - [William Roe] //! //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) use std::cell::{Cell, RefCell}; /// A container showing a type where `Cell` works with `Vec`. #[derive(Copy, Clone)] pub struct SimpleContainer { contents: i32, } /// Demonstrate how you need `Cell` even just with a `Vec`; pub fn demonstrate_need_for_cell() -> Vec> { let a_simple_container = SimpleContainer { contents: 42 }; let another_one = SimpleContainer { contents: 84 }; // The point is to illustrate vector behavior! #[allow(clippy::useless_vec)] let _a_vec = vec![a_simple_container, another_one]; // So far so good, but say we want to change the contents of one of the // struct types here. Uncomment the following line; it will fail to compile. // // let retrieved = _a_vec.get_mut(1); // // If, however, we use a `Cell`, we can get at the mutable data. See the // test below! vec![Cell::new(a_simple_container), Cell::new(another_one)] } /// Operate mutably on the contenets of an immutable reference to a `Vec`. pub fn double_cell(containers: &[Cell]) { for container_cell in containers { let old = container_cell.get().contents; let new = old * 2; container_cell.set(SimpleContainer { contents: new }); } } /// A container showing where `Cell` doesn't work and `RefCell` does. pub struct SimpleNonCopyable { contents: String, } /// Demonstrate interior mutability with `Rc` and `RefCell`. pub fn add_to_each_string(list_contained_strings: &[RefCell], to_push: &str) { for contained in list_contained_strings { let mut original = contained.borrow_mut(); original.contents.push_str(to_push); } } #[cfg(test)] mod tests { use super::*; #[test] fn need_for_cell() { // Here we have an immutable `Vec>` let all_wrapped_up = demonstrate_need_for_cell(); assert_eq!(all_wrapped_up.first().unwrap().get().contents, 42); // And yet its contents can be changed! The `Cell::set()` method lets us // update the *interior* of the item. all_wrapped_up .first() .unwrap() .set(SimpleContainer { contents: 12 }); assert_eq!(all_wrapped_up.first().unwrap().get().contents, 12); } #[test] fn double_cell_works() { use std::cell::Cell; let some_containers = vec![ Cell::new(SimpleContainer { contents: 3 }), Cell::new(SimpleContainer { contents: 5 }), ]; double_cell(&some_containers); assert_eq!(some_containers.first().unwrap().get().contents, 6); assert_eq!(some_containers.get(1).unwrap().get().contents, 10); } #[test] fn add_to_each_string_works() { use std::cell::RefCell; let contained_strings = vec![ RefCell::new(SimpleNonCopyable { contents: "Boom".to_string(), }), RefCell::new(SimpleNonCopyable { contents: "Bang".to_string(), }), ]; add_to_each_string(&contained_strings, " razzle"); assert_eq!( contained_strings.first().unwrap().borrow().contents, String::from("Boom razzle") ); assert_eq!( contained_strings.get(1).unwrap().borrow().contents, String::from("Bang razzle") ); } } ================================================ FILE: src/e017.rs ================================================ //! Point me where I need to go //! //! - **Date:** August 5, 2016 //! - **Subject:** A deep dive on references and pointers in Rust. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e017.mp3 //! //! //! //! //! Notes //! ----- //! //! By listener request, today we look at the syntax and semantics of //! referencing and dereferencing and the corresponding `&` and `*` operators. //! //! As was the case with [e016], the code samples have little to say in their //! documentation; *reading* the code will be necessary for seeing the ideas. //! //! [e016]: http://newrustacean.dev/show_notes/e016/ //! //! //! Links //! ----- //! //! - ["Inside the Fastest Font Renderer in the World"][raph] //! - The Rust Platform: //! + [original blog post][blog] //! * [Rust internals discussion][internals] //! * [Reddit discussion][reddit1] //! * [Hacker News discussion][hn1] //! + [follow-up] //! * [Reddit discussion][reddit2] //! - [Cargo vendoring support in nightly][vendoring] //! - [MIR on by default in nightly][MIR] //! - References and dereferencing: //! + _The Rust Programming Language_: //! * [References and Borrowing][book:rab] //! * [`Deref` coercions][book:deref] //! + _Rust by Example_: [Flow Control: pointers/ref][rbe] //! + The Rust Reference: //! * [Unary Operator Expressions][uoe] //! * [Pointer Types][pointer-types] //! //! [raph]: https://medium.com/@raphlinus/inside-the-fastest-font-renderer-in-the-world-75ae5270c445#.1opn7gihv //! [blog]: http://aturon.github.io/blog/2016/07/27/rust-platform/ //! [internals]: https://internals.rust-lang.org/t/proposal-the-rust-platform/3745 //! [reddit1]: https://www.reddit.com/r/rust/comments/4uxdn8/the_rust_platform_aaron_turon/? //! [hn1]: https://news.ycombinator.com/item?id=12177002 //! [follow-up]: https://internals.rust-lang.org/t/follow-up-the-rust-platform/3782 //! [reddit2]: https://www.reddit.com/r/rust/comments/4v9eo0/follow_up_to_the_rust_platform/? //! [vendoring]: https://users.rust-lang.org/t/cargo-vendoring-now-on-nightly/6776 //! [MIR]: https://github.com/rust-lang/rust/pull/34096 //! [book:rab]: https://doc.rust-lang.org/book/references-and-borrowing.html //! [book:deref]: https://doc.rust-lang.org/book/deref-coercions.html //! [rbe]: http://rustbyexample.com/flow_control/match/destructuring/destructure_pointers.html //! [uoe]: https://doc.rust-lang.org/reference.html#unary-operator-expressions //! [pointer-types]: https://doc.rust-lang.org/reference.html#pointer-types //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Cameron Mochrie //! - Cass Costello //! - [Chris Palmer] //! - [Daniel Collin] //! - [Derek Morr] //! - Doug Reeves //! - Eric Fulmer //! - Hamza Sheikh //! - [Jakub "Limeth" Hlusička] //! - [Jared Smith] //! - Keith Gray //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - [Pascal Hertleif] //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - Raph Levien //! - reddraggone9 //! - Ryan Ollos //! - Steven Murawski //! - Vesa Kaihlavirta //! - [William Roe] //! //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jared Smith]: http://twitter.com/jaredthecoder //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) /// A dummy container for use with references. pub struct DataStore<'a> { pub contents: &'a i32, } impl<'a> DataStore<'a> { pub fn new(contents: &'a i32) -> DataStore { DataStore { contents } } } /// Give a basic example of how the reference operator works. pub fn demonstrate_ref() { let twelve = 12; let ref_twelve = &twelve; // Both of these work because of the magic of automatic dereferencing, which // we'll talk about next week. println!("{:?}", twelve); println!("{:?}", ref_twelve); } /// A simple example of using the dereference operator. pub fn demonstrate_deref() { // Note here we can create a reference right out of the gate, and pass it // without applying the `&` operator again. let forty_two_ref = &42; let some_data = DataStore::new(forty_two_ref); // As above! Note that the types are not the same, but dereferencing happens // under the covers. println!("{:}", some_data.contents); println!("{:}", *some_data.contents); } /// A simple demonstration of matching against a reference type. pub fn demonstrate_match() { let four = 4; let ref_to_four = &four; // Here, if we try to reference the contents of `store` directly, we'll find // that it doesn't work: we get a type error. let store = DataStore::new(ref_to_four); // type: DataStore let optional_store = Some(store); // type: Option let contents = match optional_store { Some(store) => *store.contents, None => 0, }; println!("{:?}", contents); } ================================================ FILE: src/e018.rs ================================================ //! `Borrow`, `AsRef`, `Deref`: my head hurts now //! //! - **Date:** January 31, 2017 //! - **Subject:** Three traits which are essential for designing good, Rustic APIs. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e018.mp3 //! //! //! //! //! Notes //! ----- //! //! `Borrow`, `AsRef`, and `Deref` are a little complicated, but they're //! well-worth understanding. Together, they give you tools for dealing with //! everything from `HashMap` and friends to conversions involving smart pointer //! types to easily using `String` and `str` or `Vec` and slice together. //! //! //! Links //! ----- //! //! - `AsRef`, `Borrow`, and `Deref`: //! + [`Borrow` and `AsRef`][book-borrow-asref] in _The Rust Programming Language_ //! + [`collections::borrow::Borrow`][borrow] //! + [`std::convert::AsRef`][asref] //! + [`std::ops::Deref`][deref] //! - [persistent data structures][pds] //! - ["Rust and Rest"] – Arnin Roacher //! - [sentry-cli] //! - Particularly relevant previous episodes: //! + [e008: Just like something else][e008] //! + [e009: Composing a Rustic tune][e009] //! + [e017: Point me where I need to go][e017] //! + [interview::2: Raph Levien][interview 2] //! //! [book-borrow-asref]: https://doc.rust-lang.org/stable/book/borrow-and-asref.html //! [borrow]: https://doc.rust-lang.org/stable/collections/borrow/trait.Borrow.html //! [asref]: https://doc.rust-lang.org/stable/std/convert/trait.AsRef.html //! [deref]: https://doc.rust-lang.org/stable/std/ops/trait.Deref.html //! [pds]: https://en.wikipedia.org/wiki/Persistent_data_structure //! ["Rust and Rest"]: http://lucumr.pocoo.org/2016/7/10/rust-rest/ //! [sentry-cli]: https://github.com/getsentry/sentry-cli/ //! [e008]: https://www.newrustacean.com/show_notes/e008/ //! [e009]: https://www.newrustacean.com/show_notes/e009/ //! [e017]: https://www.newrustacean.com/show_notes/e017/ //! [interview 2]: https://www.newrustacean.com/show_notes/interview/_2/index.html //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Ben Whitley //! - Cameron Mochrie //! - [Chris Palmer] //! - [Christopher Giffard] //! - [Daniel Collin] //! - [Derek Morr] //! - [Jakub "Limeth" Hlusička] //! - Jordan Henderson //! - [Jupp Müller] //! - Keith Gray //! - Lachlan Collins //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Raph Levien //! - reddraggone9 //! - Ryan Ollos //! - Steven Murawski //! - Vesa Kaihlavirta //! - Vlad Bezden //! - [William Roe] //! - Zaki //! //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Philipp Keller]: https://twitter.com/hansapla //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) use std::borrow::Borrow; use std::convert::AsRef; use std::ops::Deref; /// A struct for showing that you cannot use `Borrow`, `AsRef` pub struct NoImplsAtAll { _contents: [u8; 8], } impl NoImplsAtAll { pub fn new(contents: &[u8; 8]) -> NoImplsAtAll { NoImplsAtAll { _contents: *contents, } } } /// Demonstrate borrowing the internal contents of the item. /// /// Note that, because of the specifics of what we're doing here, the /// implementations of `Borrow`, `AsRef`, and `Deref` here are identical. This /// will often, but not always, be the case, depending on the types and /// conversions in question. pub struct HasAllTheImpls { contents: [u8; 8], } impl HasAllTheImpls { pub fn new(contents: &[u8; 8]) -> HasAllTheImpls { HasAllTheImpls { contents: *contents, } } } impl Borrow<[u8]> for HasAllTheImpls { fn borrow(&self) -> &[u8] { &self.contents } } impl AsRef<[u8]> for HasAllTheImpls { fn as_ref(&self) -> &[u8] { &self.contents } } impl Deref for HasAllTheImpls { type Target = [u8]; fn deref(&self) -> &[u8] { &self.contents } } /// Take it implementing `Borrow<[u8]>`. pub fn takes_a_borrowable>(b: B) { for el in b.borrow() { println!("el is {}", el); } } /// Take it implementing `AsRef<[u8]>`. Note similarity to `takes_a_borrowable`. pub fn takes_a_reference>(a: A) { for el in a.as_ref() { println!("look ma, a reference! {}", el); } } /// Take the same type by `Deref` coercion at the call site. pub fn coerces_via_deref(coerced: &[u8]) { for el in coerced { println!("we borrowed it as a straight-up reference: {}", el); } } #[cfg(test)] mod tests { use super::*; #[test] fn e018_demonstrate_borrow() { let to_borrow: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; takes_a_borrowable(to_borrow); takes_a_borrowable(to_borrow.to_vec()); let borrow_this_too: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; takes_a_borrowable(borrow_this_too); let _contents_not_borrowable = NoImplsAtAll::new(&to_borrow); // would fail: // takes_a_borrowable(&_contents_not_borrowable); let contents_borrowable = HasAllTheImpls::new(&to_borrow); takes_a_borrowable(contents_borrowable); } #[test] fn e018_demonstrate_as_ref() {} #[test] fn e018_demonstrate_deref() { let basic: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; coerces_via_deref(&basic); let to_coerce = HasAllTheImpls::new(&basic); coerces_via_deref(&to_coerce); } } ================================================ FILE: src/e019.rs ================================================ //! Let's `Clone` a `Cow`! //! //! - **Date:** February 28, 2017 //! - **Subject:** The final pieces of the story for (single-threaded) memory //! management in Rust. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e019.mp3 //! //! //! //! //! Notes //! ----- //! //! Sometimes, we actually *do* need to copy types. Wouldn't it be nice if Rust //! gave us a convenient way to do that when it's convenient, or when the cost //! is low enough that the ergonomic tradeoffs are worth it? Well, perhaps //! unsurprisingly, it does! The `Copy` and `Clone` traits, plus the `Cow` type, //! give us everything we need! //! //! //! Links //! ----- //! //! - [underhanded.rs] //! //! - The typess //! //! - [`std::marker::Copy`] //! //! - ["`Copy` types" in the book][copy-book] //! //! - ["Stack-Only Data: Copy" in the new book][copy-new-book] //! //! - [7.2.0.2 Moved and copied types]: //! //! > When a local variable is used as an rvalue, the variable will be copied if its //! type implements `Copy`. All others are moved. //! //! - [Extended example in "Traits" section of new book][copy-traits-example-new-book] //! //! - [`std::clone::Clone`] //! //! - [`std::borrow::Cow`] //! //! - Default implementations //! //! - [discussion in the current book][default-book] //! //! - [discussion in the new book][default-new-book] //! //! - Supertraits //! //! - from the discussion in the reference ([6.1.9 Traits]): //! //! > Traits may inherit from other traits.... The syntax `Circle : Shape` means that types //! that implement `Circle` must also have an implementation for `Shape`. Multiple //! supertraits are separated by `+`, trait `Circle : Shape + PartialEq { }`. In an //! implementation of `Circle` for a given type `T`, methods can refer to `Shape` methods, //! since the typechecker checks that any type with an implementation of `Circle` also has //! an implementation of `Shape`... //! //! - [discussion of trait "inheritance" in the book][trait-inheritance] //! //! - [discussion of trait super- and subtyping in the new book][trait-inheritance-new-book] //! (note: still to-be-written at the time this episode was published) //! //! - Marker traits //! //! - [`std::marker`] //! //! - in the reference: [9 Special Traits] //! //! - Previous episodes on traits: //! //! - [e008: Just like something else][e008] //! //! - [e009: Composing a Rustic tune][e009] //! //! //! [underhanded.rs]: https://underhanded.rs/ //! [`std::marker::Copy`]: https://doc.rust-lang.org/stable/std/marker/trait.Copy.html //! [copy-book]: https://doc.rust-lang.org/book/ownership.html#copy-types //! [copy-new-book]: http://rust-lang.github.io/book/ch04-01-what-is-ownership.html#stack-only-data-copy //! [7.2.0.2 Moved and copied types]: https://doc.rust-lang.org/reference.html#moved-and-copied-types //! [copy-traits-example-new-book]: http://rust-lang.github.io/book/ch10-02-traits.html#fixing-the-largest-function-with-trait-bounds //! [`std::clone::Clone`]: https://doc.rust-lang.org/stable/std/clone/trait.Clone.html //! [`std::borrow::Cow`]: https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html //! [default-book]: https://doc.rust-lang.org/book/traits.html#default-methods //! [default-new-book]: http://rust-lang.github.io/book/ch10-02-traits.html#default-implementations //! [6.1.9 Traits]: https://doc.rust-lang.org/reference.html#traits //! [trait-inheritance]: https://doc.rust-lang.org/book/traits.html#inheritance //! [trait-inheritance-new-book]: http://rust-lang.github.io/book/ch19-00-advanced-features.html //! [`std::marker`]: https://doc.rust-lang.org/stable/std/marker/ //! [9 Special Traits]: https://doc.rust-lang.org/reference.html#special-traits //! [e008]: https://www.newrustacean.com/show_notes/e008/ //! [e009]: https://www.newrustacean.com/show_notes/e009/ //! //! //! Sponsors //! -------- //! //! //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - Ben Whitley //! - [Charlie Egan] //! - [Chris Palmer] //! - [Christopher Giffard] //! - [Daniel Collin] //! - [Derek Morr] //! - [Jakub "Limeth" Hlusička] //! - Jordan Henderson //! - [Jupp Müller] //! - Keith Gray //! - Lachlan Collins //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Raph Levien //! - reddraggone9 //! - Steven Murawski //! - [Stuart Hinson] //! - Tyler Harper //! - Vesa Kaihlavirta //! - Vlad Bezden //! - [William Roe] //! - Zaki //! //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Philipp Keller]: https://twitter.com/hansapla //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) /// A non-copyable point type /// /// # Examples /// /// ```rust,ignore /// # use show_notes::e019::ANoCopyOrClonePoint; /// let a_point = ANoCopyOrClonePoint::origin(); /// let moved_point = a_point; // <- moves the value /// println!("{:?}", a_point); // <- so this is a problem! /// println!("{:?}", moved_point) /// ``` /// /// The output is just what we would expect from the discussion on the show: /// /// ```plain /// error[E0382]: use of moved value: `a_point` /// --> :6:18 /// | /// 5 | let moved_point = a_point; // <- moves the value /// | ----------- value moved here /// 6 | println!("{:?}", a_point); // <- so this is a problem! /// | ^^^^^^^ value used here after move /// | /// = note: move occurs because `a_point` has type `show_notes::e019::ANoCopyOrClonePoint`, which does not implement the `Copy` trait /// ``` /// /// If we comment the offending line out, however, it compiles just fine. /// /// ```rust /// # use show_notes::e019::ANoCopyOrClonePoint; /// let a_point = ANoCopyOrClonePoint::origin(); /// let moved_point = a_point; /// // println!("{:?}", a_point); /// println!("{:?}", moved_point); // <- not a problem! /// ``` /// /// [(You can confirm this in the playground.)][playground] /// /// [playground]: https://is.gd/PZBWw0 #[derive(Debug)] pub struct ANoCopyOrClonePoint { x: f64, y: f64, z: f64, } impl ANoCopyOrClonePoint { /// Generate a point at 0, 0, 0 pub fn origin() -> ANoCopyOrClonePoint { ANoCopyOrClonePoint { x: 0.0, y: 0.0, z: 0.0, } } } /// A struct which implements `Clone` but not `Copy`. /// /// # Examples /// /// If you don't do anything, the item will be moved on assignment: /// /// ```rust,ignore /// # use show_notes::e019::BJustClonePoint; /// let a_point = BJustClonePoint::origin(); /// let cloned_point = a_point; // <- moves the value /// println!("{:?}", a_point); // <- compile error! /// println!("{:?}", cloned_point); /// ``` /// /// The output is just what we would expect from the discussion on the show: /// /// ```plain /// error[E0382]: use of moved value: `a_point` /// --> :6:18 /// | /// 5 | let cloned_point = a_point; // <- moves the value /// | ------------ value moved here /// 6 | println!("{:?}", a_point); // <- compile error! /// | ^^^^^^^ value used here after move /// | /// = note: move occurs because `a_point` has type `show_notes::e019::BJustClonePoint`, which does not implement the `Copy` trait /// ``` /// /// /// But you can manually call the `clone` method, and it will work: /// /// ```rust /// # use show_notes::e019::BJustClonePoint; /// let a_point = BJustClonePoint::origin(); /// let cloned_point = a_point.clone(); /// println!("{:?}", a_point); // <- not a problem /// println!("{:?}", cloned_point); /// ``` #[derive(Clone, Debug)] pub struct BJustClonePoint { x: f64, y: f64, z: f64, } impl BJustClonePoint { pub fn origin() -> BJustClonePoint { BJustClonePoint { x: 0.0, y: 0.0, z: 0.0, } } } /// A struct with identical behavior to `ANoCopyOrClonePoint`, except with `Copy`. /// /// Note that we have `Clone` as well as `Copy` here---we have to, since /// `Clone` is a supertrait for `Copy`. /// /// # Examples /// /// Note that this is just like the non-compiling example in [`ANoCopyOrClonePoint`], but because /// `CCopyPoint` implements `Copy`, the line which previously caused a compile /// error now works without any issue. /// /// ```rust /// # use show_notes::e019::CCopyPoint; /// let a_point = CCopyPoint::origin(); /// let copied_point = a_point; /// println!("{:?}", a_point); // <- not a problem /// println!("{:?}", copied_point) /// ``` /// /// [`ANoCopyOrClonePoint`]: /show_notes/e019/struct.ANoCopyOrClonePoint.html #[derive(Clone, Copy, Debug)] pub struct CCopyPoint { x: f64, y: f64, z: f64, } impl CCopyPoint { /// Generate a point at 0, 0, 0 pub fn origin() -> CCopyPoint { CCopyPoint { x: 0.0, y: 0.0, z: 0.0, } } } /// The `Cow` type can wrap around other types and make them "reusable". /// /// Note that the body of this function is identical with that of the body of /// the example below. /// /// # Examples /// /// We'll reuse the `BJustClonePoint` since `Cow::Owned` requires that the /// underlying type implement `Clone`. /// /// ```rust /// # use std::borrow::Cow; /// # use show_notes::e019::{BJustClonePoint,demonstrate_cow}; /// let a_point = Cow::Owned(BJustClonePoint::origin()); /// demonstrate_cow(&a_point); /// ``` /// /// Note that even though `demonstrate_cow` takes a reference to /// `BJustClonePoint`, we can pass it the `Cow` instance; this is where the /// `Deref` implementation on `Cow` comes in handy. pub fn demonstrate_cow(_point: &BJustClonePoint) {} /// What if we need a mutable reference to the wrapped type? /// /// # Examples /// /// We can get a mutable reference to the wrapped item, even if the wrapped item /// isn't itself mutable, as long as it's `Clone`-able. In this case, we're /// making a copy---this is explicit in the `to_mut()` call. If the underlying /// item isn't mutably accessible, we'll just get a mutable copy. /// /// ```rust /// # use std::borrow::Cow; /// # use show_notes::e019::{BJustClonePoint,demonstrate_mut_cow}; /// let mut a_point: Cow = Cow::Owned(BJustClonePoint::origin()); /// demonstrate_mut_cow(a_point.to_mut()); /// ``` pub fn demonstrate_mut_cow(_point: &mut BJustClonePoint) {} ================================================ FILE: src/e020.rs ================================================ //! Putting code in its place //! //! - **Date:** April 1, 2017 //! - **Subject:** How do we organize code in Rust? Where do we break it apart //! into modules or crates, and why? //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e020.mp3 //! //! //! //! //! Notes //! ----- //! //! Structuring code in a language like Rust can seem a bit more ambiguous than //! doing the same in a language with classes to attach all our functionality //! to, but in practice, the concerns are much the same: modules are namespaces, //! and we group by *responsibility*. In today's episode, I talk through that //! philosophy (and give some comparisons to other languages), and then look at //! what it looks like in practice! //! //! //! Links //! ----- //! //! - [Learning Rust Modules], by Jeff Walker, has a nice comparison of C# //! namespaces and Rust modules. //! - [The commit on Lightning inspired by this episode][lightning]. //! //! [Learning Rust Modules]: http://walkercoderanger.com/blog/2015/08/learning-rust-modules/ //! [lightning]: https://github.com/chriskrycho/lightning-rs/commit/fac341d1c1b4872d62ec05253ee33f056e67d6ce //! //! //! Sponsors //! -------- //! //! //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - Ben Whitley //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Christopher Giffard] //! - Dan Abrams //! - [Daniel Collin] //! - [Derek Morr] //! - Eugene Bulkin //! - [Jakub "Limeth" Hlusička] //! - Jordan Henderson //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Lachlan Collins //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Raph Levien //! - reddraggone9 //! - Steven Murawski //! - [Stuart Hinson] //! - Tyler Harper //! - Vesa Kaihlavirta //! - Vlad Bezden //! - Warren Harper //! - [William Roe] //! - Zaki //! //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/e021.rs ================================================ //! Keeping your types under cover //! //! - **Date:** July 17, 2017 //! - **Subject:** Using type aliases and creating custom type wrappers for //! more expressive and safer code. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e021.mp3 //! //! //! //! //! Links and Notes //! --------------- //! //! - [`Deref`] //! - [`Iterator`] //! - [`std::io::Result`] //! //! [`Deref`]: https://doc.rust-lang.org/stable/std/ops/trait.Deref.html //! [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html //! [`std::io::Result`]: https://doc.rust-lang.org/stable/std/io/type.Result.html //! //! //! Sponsors //! -------- //! //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - Dan Abrams //! - [Daniel Collin] //! - [David W. Allen] //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jonathan Turner //! - Jordan Henderson //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Sebastián Ramírez Magrí] //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Warren Harper //! - [William Roe] //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: https://twitter.com/daniel_collin //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) use std::ops::Deref; /// A type alias for a string that is appropriate to use as an email address. pub type Email = String; /// A "newtype" built by wrapping a `String` in a tuple struct. /// /// Declare it and destructure it: /// /// ``` /// # use show_notes::e021::*; /// let email = EmailStruct("hello@newrustacean.com".into()); /// let EmailStruct(the_underlying_string) = email; /// send(the_underlying_string); /// ``` /// /// Note that we can implement `map` on it: /// /// ``` /// # use show_notes::e021::*; /// let email = EmailStruct("hello@newrustacean.com".into()); /// let transformed = email.map(|value| value.replace("newrustacean", "massaffection")); /// println!("contact email for my other show is {:?}", transformed); /// ``` /// /// And we can implement a (very badly behaving) `Iterator` on it, too. (And /// I do mean *badly* behaved: do *not* attempted to use this iterator without /// setting a limit on it, as it is infinite.) /// /// ``` /// # use show_notes::e021::*; /// let mut email = EmailStruct("hello@newrustacean.com".into()); /// let next = email.next(); /// let and_the_next = email.next(); /// assert_eq!(next, and_the_next, "It always returns the same thing 😱"); /// ``` /// /// (If we wanted to implement a better-behaved iterator, we'd need to do /// substantially more work; for a good example of that on a wrapper type like /// this, see [Result] or [Option].) /// /// [Result]: https://doc.rust-lang.org/stable/std/result/enum.Result.html /// [Option]: https://doc.rust-lang.org/stable/std/option/enum.Option.html #[derive(Debug, PartialEq, Eq)] pub struct EmailStruct(pub String); impl EmailStruct { pub fn map String>(self, f: F) -> EmailStruct { let EmailStruct(the_string) = self; EmailStruct(f(the_string)) } } impl Iterator for EmailStruct { type Item = EmailStruct; fn next(&mut self) -> Option { let &mut EmailStruct(ref the_address) = self; Some(EmailStruct(the_address.clone())) } } impl Deref for EmailStruct { type Target = String; fn deref(&self) -> &String { // Return a reference to the underlying `String`, which itself // implements `Deref` for `&str`. That plus the `AsRef` impls // for each of those layers means you'll be able to write // `&EmailStruct` and simply pass it in to things expecting // `&str`. &self.0 } } /// A "newtype" built by wrapping a `String` in a single-variant enum. /// /// It's simple to use to create a wrapped variant, and then because it is /// a single-variant enum, we can also destructure it: /// /// ``` /// # use show_notes::e021::*; /// let email = EmailEnum::Address("hello@newrustacean.com".into()); /// let EmailEnum::Address(just_the_string) = email; /// send(just_the_string); /// ``` /// /// Note, however, that it is *much* more verbose. pub enum EmailEnum { Address(String), } impl Deref for EmailEnum { type Target = String; fn deref(&self) -> &String { match *self { EmailEnum::Address(ref string) => string, } } } /// A simple thing to demonstrate destructuring /// /// ``` /// # use show_notes::e021::*; /// let thing = ThingToDestructure { /// a_field: "Neat!".into(), /// another: 42, /// }; /// /// let ThingToDestructure { a_field, another: can_rename } = thing; /// println!("`a_field` is {} and another (`can_rename`) is {}", a_field, can_rename); /// ``` pub struct ThingToDestructure { /// Just a field we can destructure. pub a_field: String, /// And another field we can destructure. pub another: i32, } /// A simple function showing you can use a `String` where an `Email` is required. /// /// ``` /// # use show_notes::e021::*; /// send(String::from("hello@newrustacean.com")); /// ``` pub fn send(_to_address: Email) {} /// A function which takes a string, to use with `Deref` and `EmailStruct`. /// /// E.g. you can do this: /// /// ``` /// # use show_notes::e021::*; /// let email_struct = EmailStruct("hello@newrustacean.com".into()); /// takes_a_str(&email_struct); /// ``` /// /// And likewise, with the enum variant: /// /// ``` /// # use show_notes::e021::*; /// let email_enum = EmailEnum::Address("hello@newrustacean.com".into()); /// takes_a_str(&email_enum) /// ``` /// /// Note, however, that the `Deref` implementation is *much* more complicated /// for the enum variant, as everything is in general. pub fn takes_a_str(_some_str: &str) {} ================================================ FILE: src/e022.rs ================================================ //! `Send` and `Sync` //! //! - **Date:** January 31, 2018 //! - **Subject:** The “marker traits” that Rust uses for safe concurrency. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e022.mp3 //! //! //! //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - Guido Hoermann //! - [Hans Fjällemark] //! - Hendrik Sollich //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) use std::thread; #[doc = include_str!("../docs/e022-script.md")] pub struct Script; /// How `Send` and `Sync` work /// /// Here we have a function which spawns a thread to run `println!()`. This is /// silly, of course, but it works because (and only because!) `String` /// implements the `Send` trait. /// /// ``` /// # use std::thread; /// pub fn demo_send() { /// let foo = String::from("Hallo!"); /// thread::spawn(move || { /// println!("{}", foo); /// }); /// } /// ``` /// /// If we had a *non-`Send` type here – e.g. an `Rc` instead of just a /// `String` – we would get a compiler error: /// /// ```compile_fail /// # use std::thread; /// # use std::rc::Rc; /// pub fn will_fail() { /// let foo = Rc::new(String::from("Hallo!")); /// thread::spawn(|| { /// println!("{:?}", foo); /// }); /// } /// ``` /// /// Instead, you'll get a compiler error: /// /// ```plain /// error[E0277]: the trait bound `std::rc::Rc: std::marker::Sync` is not satisfied /// --> src/e022.rs:214:5 | /// 214 | thread::spawn(|| { /// | ^^^^^^^^^^^^^ `std::rc::Rc` cannot be shared between threads safely /// | /// = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc` /// = note: required because of the requirements on the impl of `std::marker::Send` for `&std::rc::Rc` /// = note: required because it appears within the type `[closure@src/e022.rs:214:19: 216:6 foo:&std::rc::Rc]` /// = note: required by `std::thread::spawn` ///``` /// /// Notice that it's common to see those errors together, and notice moreover /// that the error here includes *both* `Send` and `Sync`. The compiler tries to /// see if `foo` can be taken via reference, but the `Rc` type is not `Sync`, /// i.e. you cannot share references to it across threads, and that's so because /// it is not `Send`. (Strictly speaking, all `Sync` types are `Send`, but not /// all `Send` types must be `Sync`, though off the top of my head I can't think /// of a scenario where a type *would* be `Send` but *not* also `Sync`.) /// /// What's somewhat curious is that there really isn't a lot more than this to /// demo here! To get into anything more interesting in terms of /// *implementation* related to these traits, we'd have to be off in `unsafe` /// land, and we haven't talked about `unsafe` at *all* yet, so we're not going /// to do that today. However, if you want to see a good example of what makes /// for code that *can* be safely shared across threads, take a look at the /// implementation of [`Vec`] and the [`RawVec`] type it's built on! Reading the /// standard library is a really good way to learn things about Rust, and it's /// surprisingly straightforward most of the time. /// /// [`Vec`]: https://github.com/rust-lang/rust/blob/master/src/liballoc/vec.rs /// [`RawVec`]: https://github.com/rust-lang/rust/blob/master/src/liballoc/raw_vec.rs pub fn demo_send_and_sync() { let some_value = 12; thread::spawn(move || { println!("{}", some_value); }); } ================================================ FILE: src/e023.rs ================================================ //! Traits Deep Dive, Part 1 //! //! - **Date:** April 28, 2018 //! - **Subject:** Defining and using your own traits, using other crates' traits, and the orphan rule. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e023.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! Traits— //! //! - [in the Rust book][book] //! - [in Rust by Example][rbe] //! //! [book]: https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html //! [rbe]: https://rustbyexample.com/trait.html //! //! Also of interest: *specialization*: //! //! - [RFC #1210][1210] //! - recent blog posts: //! + ["Maximally minimal specialization: always applicable impls"][mm] //! + ["Sound and ergonomic specialization for Rust"][sound] //! //! [1210]: https://rust-lang.github.io/rfcs/1210-impl-specialization.html //! [PR]: https://github.com/rust-lang/rfcs/pull/1210 //! [mm]: http://smallcultfollowing.com/babysteps/blog/2018/02/09/maximally-minimal-specialization-always-applicable-impls/ //! [sound]: http://aturon.github.io/2018/04/05/sound-specialization/ //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Antonin Carette //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Brian Casiello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - Derek Buckley //! - [Derek Morr] //! - Eugene Bulkin //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - Joseph Hain //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Laurie Hedge //! - Luca Schmid //! - [Luiz Irber] //! - Mark LeMoine //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Raj Venkalil //! - [Ramon Buckley] //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Timm Preetz //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Luiz Irber]: http://luizirber.org/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckley]: http://www.inosion.com //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) use regex::Regex; #[doc = include_str!("../docs/e023-script.md")] pub struct Script; /// A trait, to be implemented by types like `Breakfast`. pub trait Eatable { /// The stuff to do *before* you eat things. (No implementation!) fn prepare(&self) -> String; /// How to eat things. (Has a default implementation.) fn eat(&self) -> String { self.prepare(); String::from("Open mouth, insert food!") } } /// Just another way to eat things – exists to show conflicting trait methods. pub trait Nomable { fn eat(&self) -> String { String::from("nom nom nom!") } } /// Breakfast is eatable, so `Breakfast` is `Eatable`! #[allow(dead_code)] pub enum Breakfast { Waffles, Cereal, Pancakes, } impl Eatable for Breakfast { fn prepare(&self) -> String { String::from(match *self { Breakfast::Cereal => "Just add milk", Breakfast::Pancakes | Breakfast::Waffles => "Butter plus syrup for the win", }) } } /// Moar Breakfast is even better, so `MoarBreakfast` is also `Eatable` and `Nomable`! #[allow(dead_code)] pub enum MoarBreakfast { Waffles, Cereal, Pancakes, FrenchToast, Bagels, } impl Nomable for MoarBreakfast {} impl Eatable for MoarBreakfast { fn prepare(&self) -> String { String::from(match *self { MoarBreakfast::Waffles | MoarBreakfast::Pancakes => "Pour syrup", MoarBreakfast::Cereal => "Add milk", MoarBreakfast::FrenchToast => "Sprinkle on powdered sugar, pour syrup", MoarBreakfast::Bagels => "Lightly toast, and spread cream cheese", }) } fn eat(&self) -> String { let preparation = self.prepare(); let consumption = match *self { MoarBreakfast::Waffles | MoarBreakfast::Pancakes | MoarBreakfast::FrenchToast => { "shovel into mouth with fork" } MoarBreakfast::Cereal => "enjoy the crunch", MoarBreakfast::Bagels => "use your fingers, of course", }; format!("{}, then {}", preparation, consumption) } } impl Eatable for Regex { fn prepare(&self) -> String { String::from("This is truly absurd.") } fn eat(&self) -> String { format!("{} But we can do it anyway!", self.prepare()) } } /// Shows how you can use traits with your own and others' types. pub fn demo_eatable() { let basic = Breakfast::Cereal; basic.eat(); let moar = MoarBreakfast::FrenchToast; Nomable::eat(&moar); let re = Regex::new("hallo").expect("'hallo' is a valid regex"); re.eat(); } ================================================ FILE: src/e024.rs ================================================ //! Traits Deep Dive, Part 2 //! //! - **Date:** June 19, 2018 //! - **Subject:** Operators as sugar for traits, traits as generic //! constraints, monomorphization, and universal and existential types. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e024.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! - on monomorphization, see also [Sean Griffin's RustConf 2017 talk][sgrc2017] //! - [zero-cost abstractions] //! //! [sgrc2017]: https://www.youtube.com/watch?v=wxPehGkoNOw //! [zero-cost abstractions]: https://blog.rust-lang.org/2015/05/11/traits.html //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Antonin Carette //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Brian Casiello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Damien Stanton //! - Dan Abrams //! - [Daniel Collin] //! - Daniel Mason //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - Derek Buckley //! - [Derek Morr] //! - Eugene Bulkin //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jon //! - Jonathan Turner //! - Joseph Hain //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Laurie Hedge //! - Luca Schmid //! - [Luiz Irber] //! - Mark LeMoine //! - Martin Heuschober //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Coish] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Raj Venkalil //! - [Ramon Buckley] //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - Ryan Osial //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Timm Preetz //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Luiz Irber]: http://luizirber.org/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckley]: http://www.inosion.com //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) use std::fmt::Display; use std::ops::Add; #[doc = include_str!("../docs/e024-script.md")] pub struct Script; /// A data structure which will implement `std::ops::Add`. /// /// With the implementation in place, we can do this: /// /// ```rust /// # use show_notes::e024::*; /// # fn main() { /// let a = Point { /// x: 123, /// y: 234, /// z: 345, /// }; /// /// let b = Point { /// x: 456, /// y: 567, /// z: 678, /// }; /// /// let c = a + b; /// # } /// ``` pub struct Point { pub x: i32, pub y: i32, pub z: i32, } impl Add for Point { type Output = Point; fn add(self, other: Point) -> Point { Point { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z, } } } /// Demonstrate a generic trait. pub trait Eatable { fn eat(&self) -> T; } impl Eatable for i32 { fn eat(&self) -> String { self.to_string() } } /// Demonstrate the ability to take a trait constraint on a generic inline. pub fn to_string_inline(t: T) -> String { format!("{}", t) } /// Demonstrate the ability to take a trait constraint on a generic with a /// `where` clause. pub fn to_string_with_where(t: T) -> String where T: Display, { format!("{}", t) } ================================================ FILE: src/e025.rs ================================================ //! Traits Deep Dive, Part 3 //! //! - **Date:** July 4, 2018 //! - **Subject:** Closure traits, `impl trait`, `dyn trait`, and object safety! //! - [**Script**][script] //! - [**Audio**][mp3] //! //! [script]: https://newrustacean.com/show_notes/e025/struct.script //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e025.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! Sponsored by [Parity Technologies][parity]! Parity is hiring Rust developers //! so if you're interested, you should check out their [job listings][jobs]! //! //! [parity]: https://paritytech.io //! [jobs]: https://paritytech.io/jobs/ //! //! ### Links //! //! - [RFC #1733: Trait Aliases][1733] //! - [RFC #255: Object Safety][255] //! - [Ch. 17 in the Second Edition of *The Rust Programming Language*][trpl] //! - [Huon Wilson's post][huon] //! //! [1733]: https://github.com/rust-lang/rfcs/blob/master/text/1733-trait-alias.md //! [255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md //! [trpl]: https://doc.rust-lang.org/book/second-edition/ch17-02-trait-objects.html //! [huon]: https://huonw.github.io/blog/2015/05/where-self-meets-sized-revisiting-object-safety/ "Where Self Meets Sized: Revisiting Object Safety" //! //! ### Example //! //! You can see all of the pieces of the final example described in the show //! here (and the module has the required definitions for `Point`). //! //! ```rust //! # use show_notes::e025::*; //! # fn main() { //! let points = vec![ //! Point { x: 1.0, y: 2.0 }, //! Point { x: 12.0, y: 4.3 }, //! Point { x: -5.4, y: 18.7 }, //! ]; //! //! let origin = Point::default(); //! //! // This is the version we start with. It works fine, but it's not elegant. //! let distances_inline: Vec = points //! .iter() //! .map(|point| { //! let change = point - &origin; //! (change.x.powi(2) + change.y.powi(2)).sqrt() //! }) //! .collect(); //! //! // This version is *much* cleaner! //! let distances_impl: Vec = points.iter().map(distance_from_impl(&origin)).collect(); //! # } //! ``` //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Kryvomaz //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Antonin Carette //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Brian Casiello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Damien Stanton //! - Dan Abrams //! - [Daniel Collin] //! - Daniel Mason //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - Derek Buckley //! - [Derek Morr] //! - Eugene Bulkin //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jon //! - Jonathan Turner //! - Joseph Hain //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Laurie Hedge //! - Luca Schmid //! - [Luiz Irber] //! - Mark LeMoine //! - Martin Heuschober //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Coish] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Raj Venkalil //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Robert Chrzanowski] //! - [Ryan Blecher] //! - Ryan Osial //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Luiz Irber]: http://luizirber.org/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robert Chrzanowski]: https://github.com/zirman //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) use std::{f32, ops::Sub}; #[derive(Default)] pub struct Point { pub x: f32, pub y: f32, } impl<'p> Sub for &'p Point { type Output = Point; fn sub(self, other: &Point) -> Point { Point { x: self.x - other.x, y: self.y - other.y, } } } pub fn distance_from_boxed<'a, 'b: 'a>(offset: &'b Point) -> Box f32 + 'a> { Box::new(move |point| { let change = point - offset; (change.x.powi(2) + change.y.powi(2)).sqrt() }) } pub type DistanceFrom<'a> = Box f32 + 'a>; pub fn distance_from_alias<'a, 'b: 'a>(offset: &'b Point) -> DistanceFrom<'a> { Box::new(move |point| { let change = point - offset; (change.x.powi(2) + change.y.powi(2)).sqrt() }) } pub fn distance_from_impl<'a, 'b: 'a>(offset: &'b Point) -> impl FnMut(&'a Point) -> f32 { move |point| { let change = point - offset; (change.x.powi(2) + change.y.powi(2)).sqrt() } } #[doc = include_str!("../docs/e025-script.md")] pub struct Script; ================================================ FILE: src/e026.rs ================================================ //! Functional Programming Ideas //! //! - **Date:** July 24, 2018 //! - **Subject:** How Rust both borrows from FP languages and charts its own, //! very different course. //! - [**Script**][script] //! - [**Audio**][mp3] //! //! [script]: https://newrustacean.com/show_notes/e026/struct.script //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e026.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! Sponsored by [Parity Technologies][parity]! Parity is hiring Rust developers //! so if you're interested, you should check out their [job listings][jobs]! //! //! [parity]: https://paritytech.io //! [jobs]: https://paritytech.io/jobs/ //! //! ### Links //! //! - [_Maybe Haskell_][mh] //! - ["shared mutable state is the root of all evil"][sms] //! - ["code smells"][smells] //! - [Persistent Data Types/Structures][pdts] //! - [`rpds` crate][rpds] //! - [immutable.rs][im] //! //! [mh]: https://gumroad.com/l/maybe-haskell/ //! [sms]: https://henrikeichenhardt.blogspot.com/2013/06/why-shared-mutable-state-is-root-of-all.html //! [smells]: https://en.wikipedia.org/wiki/Code_smell //! [pdts]: https://en.wikipedia.org/wiki/Persistent_data_structure //! [rpds]: https://github.com/orium/rpds //! [im]: http://immutable.rs/ //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Kryvomaz //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Antonin Carette //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Brian Casiello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Damien Stanton //! - Dan Abrams //! - [Daniel Collin] //! - Daniel Mason //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - Derek Buckley //! - [Derek Morr] //! - Eugene Bulkin //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jon //! - Jonathan Turner //! - Joseph Hain //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Laurie Hedge //! - Luca Schmid //! - [Luiz Irber] //! - Mark LeMoine //! - Martin Heuschober //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Coish] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Raj Venkalil //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Robert Chrzanowski] //! - [Ryan Blecher] //! - Ryan Osial //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Luiz Irber]: http://luizirber.org/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robert Chrzanowski]: https://github.com/zirman //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../docs/e026-script.md")] pub struct Script; ================================================ FILE: src/e027.rs ================================================ //! Trust Me; I Promise! //! //! - **Date:** November 30, 2018 //! - **Subject:** An intro to `unsafe` Rust and Rust's idea of safety. //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e027.mp3 //! [script]: https://newrustacean.com/show_notes/e027/struct.script //! //! //! //! Show Notes //! ---------- //! //! ### Errata //! //! A quick correction: on the show I said that a trait needed to be unsafe when //! it had an `unsafe fn` method. This isn't correct: safe traits can have //! unsafe methods, and unsafe traits can exist without any methods at all (as //! implied by my reference to `Send` and `Sync`). You can see this in practice //! in the following example, which compiles just fine! //! //! ``` //! trait ASafeTrait { //! unsafe fn unsafe_method() {} //! } //! //! unsafe trait AnUnsafeTrait {} //! ``` //! //! The idea of an `unsafe` trait is that it has some conditions which you must //! uphold to safely implement it – again, just as with `Send` and `Sync`. In //! the case of most traits, this will be because some trait method has //! invariants it needs to hold else it would cause undefined behavior. For //! another example of this, see the (unstable as of the time of recording) //! trait [`std::iter::TrustedLen`]. //! //! [`std::iter::TrustedLen`]: https://doc.rust-lang.org/nightly/std/iter/trait.TrustedLen.html //! //! Thanks to Rust language team member [@centril] for noting this to me after //! listening when I was recording the show live! //! //! [@centril]: https://github.com/centril //! //! ### Links //! //! - [_The Rust Programming Language_, Chapter 19: Unsafe][book] //! - [The Nomicon][nomicon] //! - ["Rust and OpenGL from Scratch", by Nerijus Arlauskas][opengl] //! //! [book]: https://doc.rust-lang.org/book/2018-edition/ch19-01-unsafe-rust.html //! [nomicon]: https://doc.rust-lang.org/nomicon/README.html //! [opengl]: http://nercury.github.io/rust/opengl/tutorial/2018/02/08/opengl-in-rust-from-scratch-00-setup.html //! //! //! ### Examples //! //! #### Borrow-checked code in `unsafe` //! //! ``` //! let mut f = String::from("foo"); //! //! unsafe { //! let borrowed = &mut f; //! //! // This would be unsafe and throw an error (before Rust 2018): //! // let borrow_again = &f; //! //! println!("{}", borrowed); //! //! // This would be unsafe and throw an error: //! // println!("{}", borrow_again); //! } //! ``` //! //! [(See it in a playground)][safe `unsafe`] //! //! [safe `unsafe`]: https://play.rust-lang.org/?version=beta&mode=release&edition=2018&gist=38d1089cdc3a4148609e9e3bbbfd002c //! //! ##### Safely mutating a raw pointer //! //! ``` //! let f = Box::new(12); //! let mut g = Box::into_raw(f); //! g = &mut 10; //! ``` //! //! [(See it in a playground)][safe mutate] //! //! [safe mutate]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=3a7a9facd0f67d4a590afc3a3ecef95b //! //! Sponsors //! -------- //! //! Thanks to Parity for sponsoring the show again. Go check out their [***Rust //! jobs***][parity]! //! //! [parity]: https://paritytech.io/jobs/ //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Payne //! - Alexander Kryvomaz //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Bryce Johnston //! - Caryn Finkelman //! - Cass Costello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Daniel //! - Dan Abrams //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Hewson //! - [Derek Morr] //! - Doug Reeves //! - Eugene Bulkin //! - Fábio Botelho //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - Jerome Froelich //! - [Joar Wandborg]: Joar Wandborg //! - [John Rudnick] //! - Jon //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Marhee //! - Justin Ossevoort //! - Kai Yao //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Steffen Loen Sunde] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Zak van der Merwe //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Joar Wandborg]: http://github.com/joar //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Steffen Loen Sunde]: https://www.ntnu.edu/employees/steffen.sunde //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../docs/e027-script.md")] pub struct Script; ================================================ FILE: src/e028.rs ================================================ //! Meet My Associates //! //! - **Date:** February 21, 2019 //! - **Subject:** Associated items: functions and methods, constants, types, //! and (very briefly!) GATs. //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e028.mp3 //! [script]: https://newrustacean.com/show_notes/e027/struct.script //! //! //! //! Show Notes //! ---------- //! //! - [`Iterator` source][the source] //! - [the first Traits deep dive episode] //! - [RFC #1598] //! - [RFC #195] //! - [The Reference on associated items][reference] //! - [Rust 1.20] //! - [deals.manning.com/new-rustacean] //! //! [the source]: https://doc.rust-lang.org/1.32.0/src/core/iter/iterator.rs.html&version=1.32.0 //! [the first Traits deep dive episode]: https://newrustacean.com/show_notes/e023/ //! [RFC #1598]: https://github.com/rust-lang/rfcs/blob/master/text/1598-generic_associated_types.md //! [RFC #195]: https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md //! [reference]: https://doc.rust-lang.org/reference/glossary.html#associated-item //! [Rust 1.20]: https://newrustacean.com/show_notes/news/rust_1_20/ //! [deals.manning.com/new-rustacean]: http://bit.ly/2OXnlEb //! //! Sponsors //! -------- //! //! Thanks to Manning for sponsoring the show *and* giving all of you a 40%-off //! discount on their whole store (but especially Carol Nichols' and Jake //! Goulding's _Rust in Motion_ video content and the _Rust in Action_ MEAP!) at //! [deals.manning.com/new-rustacean][manning] //! //! [manning]: http://bit.ly/2OXnlEb //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Lozada //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - Arlen Haftevani //! - [Arlo (Hyena)] //! - [beaorn] //! - [Behnam Esfahbod] //! - [Benjamin Manns] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Cat Dad //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Christoffer Ceutz //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Carroll //! - David Hewson //! - [Derek Morr] //! - Doug Reeves //! - [Douglas Correa] //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - Evan Stoll //! - [Fabio (decathorpe)] //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - Hoàng Đức Hiếu //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - [Jason Bowen] //! - [Jendrik Illner] //! - Jerome Froelich //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - Jonah //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Mou //! - Joseph Schrag //! - [Joe Percy] //! - Justin Ossevoort //! - Kai Yao //! - Kazutaka Mise //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Malnormalulo] //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - [Michael Melanson] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Soren Bramer Schmidt] //! - [Steffen Loen Sunde] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Zak van der Merwe //! - Zachary Snyder //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [Arlo (Hyena)]: https://asonix.dog/@asonix //! [beaorn]: https://github.com/beaorn //! [Behnam Esfahbod]: https://github.com/behnam //! [Benjamin Manns]: https://www.benmanns.com/ //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Douglas Correa]: http://learnrust.io/ //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Evan Stoll]: https://github.com/evanjs //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jason Bowen]: https://twitter.com/jwbowen //! [Jendrik Illner]: https://www.jendrikillner.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [Joe Percy]: http://joetdc.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Malnormalulo]: https://twitter.com/Malnormalulo //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Michael Melanson]: https://www.michaelmelanson.net //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Soren Bramer Schmidt]: http://prisma.io/ //! [Steffen Loen Sunde]: https://www.ntnu.edu/employees/steffen.sunde //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../docs/e028-script.md")] pub struct Script; ================================================ FILE: src/e029/ffi-demo.c ================================================ #include "ffi-demo.h" int add(int a, int b) { return a + b; } void translate(Point * point, float byX, float byY) { point->x += byX; point->y += byY; } ================================================ FILE: src/e029/ffi-demo.h ================================================ int add(int a, int b); typedef struct Point { float x; float y; } Point; void translate(Point * point, float byX, float byY); ================================================ FILE: src/e029/mod.rs ================================================ //! I’m Out to C //! //! - **Date:** April 3, 2019 //! - **Subject:** Using Rust’s Foreign Function Interface (FFI) with C! //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e029.mp3 //! [script]: https://newrustacean.com/show_notes/e029/struct.script //! //! //! //! Show Notes //! ---------- //! //! The code samples here directly match the things I described in the show, so //! you will likely want to look at [`add`] and [`ffi::add`], then [`Point`], //! [`translate`], and [`ffi::translate`] in that order. //! //! [`add`]: ./fn.add.html //! [`ffi::add`]: ./ffi/fn.add.html //! [`Point`]: ./struct.Point.html //! [`translate`]: ./fn.translate.html //! [`ffi::translate`]: ./ffi/fn.translate.html //! //! ### Links //! //! Other helpful Rust FFI discussions: //! //! - [The Rust Programming Language’s materials] //! - the [nomicon] //! - [Rust FFI Omnibus] //! - the [Reference’s] discussion //! - the associated Rust [API] docs //! //! [nomicon]: https://doc.rust-lang.org/beta/nomicon/ffi.html //! [Rust FFI Omnibus]: http://jakegoulding.com/rust-ffi-omnibus/ //! [deals.manning.com/new-rustacean]: http://bit.ly/2OXnlEb //! [The Rust Programming Language’s materials]: https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code //! [Reference’s]: https://doc.rust-lang.org/1.33.0/reference/items/external-blocks.html //! [API]: https://doc.rust-lang.org/1.33.0/std/keyword.extern.html //! //! Sponsors //! -------- //! //! Thanks to Manning for sponsoring the show *and* giving all of you a 40%-off //! discount on their whole store (but especially Carol Nichols' and Jake //! Goulding's _Rust in Motion_ video content and the _Rust in Action_ MEAP!) at //! [deals.manning.com/new-rustacean][manning] //! //! [manning]: http://bit.ly/2OXnlEb //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Lozada //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - Arlen Haftevani //! - [Arlo (Hyena)] //! - Arun Kulshreshtha //! - [Behnam Esfahbod] //! - [Benjamin Manns] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Cat Dad //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Christoffer Ceutz //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Carroll //! - David Hewson //! - [Derek Morr] //! - Doug Reeves //! - [Douglas Correa] //! - Edmund Kump //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - [Evan Stoll] //! - [Fabio (decathorpe)] //! - [Fabio Correa] //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - Hoàng Đức Hiếu //! - Hugo Josefson //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - [Jason Bowen] //! - [Jendrik Illner] //! - Jerome Froelich //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - Jonah //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Mou //! - Joseph Schrag //! - [Joe Percy] //! - Justin Ossevoort //! - Kai Yao //! - Kazutaka Mise //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Malnormalulo] //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - [Michael Melanson] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Oladapo Fadeyi //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Soren Bramer Schmidt] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Zak van der Merwe //! - Zachary Snyder //! - [Zach Peters] //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [Arlo (Hyena)]: https://asonix.dog/@asonix //! [Behnam Esfahbod]: https://github.com/behnam //! [Benjamin Manns]: https://www.benmanns.com/ //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Douglas Correa]: http://learnrust.io/ //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Evan Stoll]: https://github.com/evanjs //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Fabio Correa]: https://linkedin.com/in/feamcor //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jason Bowen]: https://twitter.com/jwbowen //! [Jendrik Illner]: https://www.jendrikillner.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [Joe Percy]: http://joetdc.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Malnormalulo]: https://twitter.com/Malnormalulo //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Michael Melanson]: https://www.michaelmelanson.net //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Soren Bramer Schmidt]: http://prisma.io/ //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! [Zach Peters]: https://github.com/zpeters //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) use std::os::raw::c_float; #[doc = include_str!("../../docs/e029-script.md")] pub struct Script; /// An example of a slightly more complex data structure we can use with FFI. /// /// Note the `#[repr(C)]`, which tells Rust to make sure this struct is laid out /// the way that the C ABI expects. That's *not* the way that Rust's own ABI /// (which is unstable and can change at any time) might lay it out. /// /// Note also that `x` and `y` are `c_float`, which is [a type alias][c_float] /// for `f32`. We use it here to make explicit the interop, and also because it /// is *possible* that it might change on some specific operating system. If we /// went to compile for an operating system where C's `float` type were *not* a /// 32-point floating bit number (and the C standard does not require it to be /// anything but "a floating point number"), the compiler would let us know. /// /// [c_float]: https://doc.rust-lang.org/1.33.0/std/os/raw/type.c_float.html #[repr(C)] #[derive(Debug, PartialEq)] pub struct Point { pub x: c_float, pub y: c_float, } /// The module with all the unsafe code in it! You'll want to poke at this! /// /// (Note that this is private, and we wouldn't normally make this kind of code /// visible in documentation at all. Instead, we would *only* make public the /// safe abstraction around it which we're providing at the root of this module /// (see [e027]!). I've set a `RUSTDOCFLAGS` value in the `Makefile` at the root /// of the repo so you get these docstring notes for it!) /// /// [e027]: https://newrustacean.com/show_notes/e027/ mod ffi { use super::Point; use std::os::raw::{c_float, c_int}; extern "C" { /// A *mostly*-trivial example: addition in C instead of in Rust. (See /// the docs for `e029::add` for why it *isn't* totally trivial.) /// /// You can use it in an `unsafe` block like so: /// /// ```rust,ignore /// unsafe { /// let result = add(1, 2); // 3, of course! /// } /// ``` pub(super) fn add(a: c_int, b: c_int) -> c_int; /// An example of a C function we can call with an object. /// /// You can use it in an `unsafe` block like so: /// /// ```rust,ignore /// let mut point = Point { x: 0.0, y: 0.0 }; /// unsafe { /// translate(&mut point, 12.3, 14.4); /// } /// assert_eq!(point, Point { x: 12.3, y: 14.4 }); /// ``` /// /// [e027]: https://newrustacean.com/show_notes/e027/ pub(super) fn translate(point: *mut Point, by_x: c_float, by_y: c_float); } } /// A safe interface for the unsafe `ffi::add`. /// /// Note that this particular check is as silly as calling out to C for addition /// is, but it shows how you can provide a safe wrapper for a case where C's /// implementation differences *might* actually matter to you. /// /// While it might seem that something like addition is trivially safe, it turns /// out to be *mostly* safe. The behavior of overflow for signed integers is /// *not defined* for C. In Rust, it *is* defined, by [RFC #0560]: in modes /// where `debug_assertions` are enabled, an overflow will cause a panic; in /// modes where those assertions are not enabled (i.e. release mode), Rust wraps /// them by [two's complement]. The net of that is that even something this /// simple can have unexpected results when calling across the FFI boundary. /// /// [RFC #0560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md /// [two's complement]: https://en.wikipedia.org/wiki/Two's_complement /// /// ```rust /// # use show_notes::e029::add; /// assert_eq!(add(1, 2), Some(3)); /// ``` pub fn add(a: i32, b: i32) -> Option { if i32::max_value() - a >= b { unsafe { Some(ffi::add(a, b)) } } else { None } } /// A safe interface for the unsafe `ffi::translate` function. /// /// In this case, there are no invariants we need to maintain other than those /// which Rust *always* maintains, i.e. that the reference we have with /// `&mut Point` is a valid reference (not `null`, actually points to a `Point`, /// and so on). Since Rust guarantees this, we can simply *directly* call the /// unsafe extern function here. /// /// I explicitly included the cast `as *mut Point`, but an `&mut Point` will be /// automatically converted to a `*mut Point` when needed, so it is unnecessary /// from a compiler perspective. It may, however, be helpful for making your /// intent clear to other users! /// /// ```rust /// # use show_notes::e029::{translate, Point}; /// let mut point = Point { x: 0.0, y: 0.0 }; /// translate(&mut point, 2.4, 4.8); /// assert_eq!(point, Point { x: 2.4, y: 4.8 }); /// ``` pub fn translate(point: &mut Point, by_x: f32, by_y: f32) { unsafe { ffi::translate(point as *mut Point, by_x as c_float, by_y as c_float); } } ================================================ FILE: src/e030.rs ================================================ //! Can You See Me Now? //! //! - **Date:** April 26, 2019 //! - **Subject:** Item visibility and `pub()` as API design tools. //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e030.mp3 //! [script]: https://newrustacean.com/show_notes/e030/struct.script //! //! //! //! Show Notes //! ---------- //! //! The easiest and most effective way to understand the example in this case //! will simply be to look directly at [the source code][src]. You *can* read //! the docs for each of the nested modules, but you'll be doing a *lot* of //! navigating around for that. //! //! [src]: /src/show_notes/e030.rs.html //! //! Also, I am using Cargo’s `--document-private-items` flag, so that you can //! see *all* the items in *all* the modules, even those which are not public, //! but note that usually you would not see docs for those! //! //! ### Links //! //! - [the reference on visibility] //! - [RFC #1422] //! - [episode source code] //! - [e020] //! //! [the reference on visibility]: https://doc.rust-lang.org/reference/visibility-and-privacy.html //! [RFC #1422]: https://github.com/rust-lang/rfcs/blob/master/text/1422-pub-restricted.md //! [episode source code]: https://newrustacean.com/src/show_notes/e030.rs.html //! [e020]: https://newrustacean.com/show_notes/e020/ //! //! Sponsors //! -------- //! //! Thanks to Manning for sponsoring the show *and* giving all of you a 40%-off //! discount on their whole store (but especially their [WebAssembly in //! Action MEAP][MEAP]) at [deals.manning.com/new-rustacean][manning]! //! //! [manning]: http://bit.ly/2OXnlEb //! [MEAP]: https://www.manning.com/books/webassembly-in-action //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Lozada //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - Arlen Haftevani //! - [Arlo (Hyena)] //! - Arun Kulshreshtha //! - [Behnam Esfahbod] //! - [Benjamin Manns] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Cat Dad //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Christoffer Ceutz //! - Cristian Paul //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Carroll //! - David Hewson //! - [Derek Morr] //! - Dominic Cooney //! - Doug Reeves //! - [Douglas Correa] //! - Edmund Kump //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - [Evan Stoll] //! - [Fabio (decathorpe)] //! - [Fabio Correa] //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - Hoàng Đức Hiếu //! - [Hugo Josefson] //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - [Jason Bowen] //! - [Jeff May] //! - [Jendrik Illner] //! - Jerome Froelich //! - JockeTF //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - Jonah //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Mou //! - Joseph Schrag //! - [Joe Percy] //! - Justin Ossevoort //! - Kai Yao //! - Kazutaka Mise //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Malnormalulo] //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - [Michael Melanson] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Oladapo Fadeyi //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - Romain Chossart //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Soren Bramer Schmidt] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - Zak van der Merwe //! - Zachary Snyder //! - [Zach Peters] //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [Arlo (Hyena)]: https://asonix.dog/@asonix //! [Behnam Esfahbod]: https://github.com/behnam //! [Benjamin Manns]: https://www.benmanns.com/ //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Douglas Correa]: http://learnrust.io/ //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Evan Stoll]: https://github.com/evanjs //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Fabio Correa]: https://linkedin.com/in/feamcor //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Hugo Josefson]: https://www.hugojosefson.com //! [Jason Bowen]: https://twitter.com/jwbowen //! [Jeff May]: https://gitlab.com/jeffmay //! [Jendrik Illner]: https://www.jendrikillner.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [Joe Percy]: http://joetdc.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Malnormalulo]: https://twitter.com/Malnormalulo //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Michael Melanson]: https://www.michaelmelanson.net //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Soren Bramer Schmidt]: http://prisma.io/ //! [Stuart Hinson]: http://stuarth.github.io/ //! [Zach Peters]: https://github.com/zpeters //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - [Patreon](https://www.patreon.com/newrustacean) //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../docs/e030-script.md")] pub struct Script; /// One of two internal modules (with `right`) for demonstrating visibility. pub mod left { /// Visible to other items in `left`, including in sub-modules. fn local() {} /// `pub(crate) mod a` is visible everywhere within the crate that can see /// `left`, but hidden from all external callers. pub(crate) mod a { /// This is visible everywhere in the crate that can see `a`. Open the /// source to see all the other items it can interact with! pub fn demo() { // We can see other items in `left` or `a` regardless of visibility. super::local(); sibling(); // We can see other items which are marked as visible within `left`. crate::e030::left::b::demo(); // We can see other items which are marked as visible within `e030`, // whether direct siblings to us or not. crate::e030::left::c::demo(); super::c::demo(); crate::e030::right::s::demo(); // We can see other items which are marked as visible within the // crate. crate::e030::right::q::demo(); // This won't compile because `crate::e030::right::r` is not visible // here: it is only visible within `crate::e030::right`. // crate::e030::right::r::demo(); // We also cannot see items in `child` unless they are some `pub` // variant. // super::private_child::only_in_child(); // But we can // super::private_child::also_only_in_child(); } /// `fn sibling` is visible only to other items within `a`. fn sibling() {} /// `mod child` here is visible to `a`, but not outside `a` -- including /// even is siblings. mod private_child { /// `fn only_in_child` is not visible to anything outside `child`. fn only_in_child() {} /// `pub fn also_only_in_child` is also hidden to anything outside /// `child`. pub fn also_only_in_child() {} } } /// `pub(in crate::e030::left) mod b` is visible to pub(in crate::e030::left) mod b { /// This is visible everywhere in the crate that can see `b`. Open /// the source to see how all the other items it can interact with! pub fn demo() {} } pub(in crate::e030) mod c { /// This is visible everywhere in the crate that can see `b`. Open the /// source to see how all the other items it can interact with! pub fn demo() {} } } /// One of two internal modules (with `left`) for demonstrating visibility. pub mod right { /// This is visible *within* the crate everywhere that can see `right`. pub(crate) mod q { /// This is visible everywhere in the crate that can see `q`. Visibility /// exactly mirrors `crate::e030::left::a::demo`. pub fn demo() {} } /// This is visible everywhere in `right`, including in `q`. pub(in crate::e030::right) mod r { /// This is visible everywhere in the crate that can see `s`. Open /// the source to see how all the other items it can interact with! pub fn demo() {} } /// This is visible everywhere in the e030 module. pub(in crate::e030) mod s { pub fn demo() {} } } ================================================ FILE: src/e031/e031.c ================================================ #include #include #include "e031.h" void section() { printf("\n---\n\n"); } int main() { // --- Start easy: just numbers. --- // section(); int a = 123; int b = 456; printf("Added `%d` to `%d` in Rust, and got back `%d`.\n", a, b, add_in_rust(123, 456)); // --- Strings are a mite more interesting. --- // section(); // We start by allocating a couple strings on the C side. char *greeting = "Hello, "; char *name = "Rustacean!"; // Then we get the result of concatenating them in Rust, and we get back a // pointer to memory that Rust owns. char *joined = concat_strings(greeting, name); printf("A greeting: `%s`\n", joined); // We always need to free memory when we're done; otherwise we create a // memory leak. However, because Rust owns this memory, Rust needs to free // it! We effectively have an unsafe mutable reference to memory which Rust // is keeping alive -- returning it this way lets Rust drop it. free_rust_string(joined); // --- What about structs? --- // section(); // Start by allocating a point. point_t point = {.x = 0.4, .y = 05}; printf("`point` starts at `%.1f, %.1f`.\n", point.x, point.y); // Then translate it, using the Rust function. float byX = 4.8; float byY = 5.9; point_translate(&point, byX, byY); printf("After transposing `point.x` by `%.1f` and `point.y` by `%.1f`, " "`point` is at `%.1f, %.1f`.\n", byX, byY, point.x, point.y); // But because we have access to the internals on the C side, we can also // mutate it here. This is *okay*, but it means Rust has no control, and we // have to keep track of who has done what to it. And shared mutable state // is the root of all evil; this is *not* what we want. point.x = 43.4; point.y = 55.5; printf("...and we just mutated it on the C side to `%.1f, %.1f`.\n", point.x, point.y); // We don't need to call `point_free` here because we allocated it on the C // side, and in fact if we *did*, we could be introducing other oddities. We // only need to do `point_free` if we allocate on the Rust side. For that, // see the *next* section. // --- Now, for opaque pointers! --- // section(); // Here, we are getting an `OpaquePoint` from Rust, and the *only* way we // can construct such a point is by using the means Rust supplies. This is // helpful because it means we can actually maintain the type's internal // variants however it needs to, and can use privacy effectively as // discussed in e030. opaque_point_t *opaquePoint = opaque_point_new(-4.5, 2.5); // Similarly, we can only *operate* on it using Rust-exposed functions. We // don't have access to its internal layout or even know anything about it, // so if we want a description, we need to let Rust supply it. Note that, as // in the string example above, we're allocating a string here and we need // to be sure to call free on it! If we call `opaque_point_describe` in an // inline form -- // // printf("`opaquePoint` starts at %s.\n", // opaque_point_describe(opaquePoint)); // // -- we would end up with a memory leak, because we would have no way to // free the reference returned by Rust. char *description; description = opaque_point_describe(opaquePoint); printf("`opaquePoint` starts at %s.\n", description); free_rust_string(description); // Unlike with `Point`, we *cannot* simply mutate this one on the C side (or // in any other language consuming it via C FFI). Instead, we must used the // `opaque_point_translate` function to do it. This works identically to how // `point_translate` works; it's just that this is the *only* way to do it. float opaqueByX = 8.8; float opaqueByY = -1.0; opaque_point_translate(opaquePoint, opaqueByX, opaqueByY); // Once again we're allocating a string on the Rust side we'll need to free. description = opaque_point_describe(opaquePoint); printf("After transposing `opaquePoint.x` by `%.1f` and `opaquePoint.y` by " "`%.1f`, `opaquePoint` is at %s.\n", opaqueByX, opaqueByY, description); // And here we do just that. free_rust_string(description); // And we also need to free `opaquePoint` so we don't leak *its* memory. opaque_point_free(opaquePoint); } ================================================ FILE: src/e031/e031.h ================================================ /// The `add_in_rust` function exported by the Rust crate. extern int add_in_rust(int a, int b); /// The `concat_strings` function exported by the Rust crate. extern char *concat_strings(char const *const first, char const *const second); /// The `free_rust_string` function exported by the Rust crate. extern void free_rust_string(char *to_free); /// The `Point` type declared by Rust. We're not making this opaque; see below. typedef struct point { float x; float y; } point_t; /// The `point_translate` function declared by Rust. Mutates `point`! void point_translate(point_t *point, float byX, float byY); /// An opaque type: C cannot do anything with the internals, unlike `point_t`. typedef struct opaque_point opaque_point_t; /// The `opaque_point_new` function declared by Rust. Gets us a `point`! opaque_point_t *opaque_point_new(float x, float y); /// The `opaque_point_translate` function declared by Rust. Mutates `point`! void opaque_point_translate(opaque_point_t *point, float byX, float byY); /// The `opaque_point_describe` function declared by Rust. Must free the string /// it returns! char *opaque_point_describe(opaque_point_t *point); /// The `opaque_point_free` function declared by Rust. void opaque_point_free(opaque_point_t *point); ================================================ FILE: src/e031/mod.rs ================================================ //! FFI Deep Dive //! //! - **Date:** May 11, 2019 //! - **Subject:** Exposing Rust types and functions to C API consumers. //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e031.mp3 //! [script]: https://newrustacean.com/show_notes/e031/struct.script //! //! //! //! Show Notes //! ---------- //! //! It's impossible to make the declarations below follow the order I talked //! through them on the recording without also making them horrible to read, so //! just use this outline instead: //! //! 1. [`add_in_rust`][1] //! 2. Strings //! 1. [`concat_strings`][2] //! 2. [`free_rust_string`][3] //! 3. [`Point`][4] //! 1. [`point_translate`][5] //! 4. [`union`][6] //! 5. [`OpaquePoint`][7] //! 1. [`opaque_point_new`][8] //! 2. [`opaque_point_translate`][9] //! 3. [`opaque_point_free`][10] //! //! [1]: https://newrustacean.com/show_notes/e031/fn.add_in_rust.html //! [2]: https://newrustacean.com/show_notes/e031/fn.concat_strings.html //! [3]: https://newrustacean.com/show_notes/e031/fn.free_rust_string.html //! [4]: https://newrustacean.com/show_notes/e031/struct.Point.html //! [5]: https://newrustacean.com/show_notes/e031/fn.point_translate.html //! [6]: https://newrustacean.com/show_notes/e031/unions/index.html //! [7]: https://newrustacean.com/show_notes/e031/struct.OpaquePoint.html //! [8]: https://newrustacean.com/show_notes/e031/fn.opaque_point_new.html //! [9]: https://newrustacean.com/show_notes/e031/fn.opaque_point_translate.html //! [10]: https://newrustacean.com/show_notes/e031/fn.opaque_point_free.html //! //! ### Links //! //! - [Rust FFI Omnibus] //! - [the repository for the show] //! - [RFC #2195] //! //! [Rust FFI Omnibus]: http://jakegoulding.com/rust-ffi-omnibus/ //! [the repository for the show]: https://github.com/chriskrycho/newrustacean.com //! [RFC #2195]: https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md //! //! Sponsors //! -------- //! //! Thanks to Parity for sponsoring the show and hiring Rust developers! //! //! [parity]: https://www.parity.io/jobs //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Lozada //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - Arlen Haftevani //! - [Arlo (Hyena)] //! - Arun Kulshreshtha //! - [Behnam Esfahbod] //! - [Benjamin Manns] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Cat Dad //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Christoffer Ceutz //! - Cristian Paul //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Carroll //! - David Hewson //! - [Derek Morr] //! - Dominic Cooney //! - Doug Reeves //! - [Douglas Correa] //! - Edmund Kump //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - [Evan Stoll] //! - [Fabio (decathorpe)] //! - [Fabio Correa] //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - Hoàng Đức Hiếu //! - [Hugo Josefson] //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - [Jason Bowen] //! - [Jeff May] //! - [Jendrik Illner] //! - Jerome Froelich //! - JockeTF //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - Jonah //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Mou //! - Joseph Schrag //! - [Joe Percy] //! - Justin Ossevoort //! - Kai Yao //! - Kazutaka Mise //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Malnormalulo] //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - [Michael Melanson] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Oladapo Fadeyi //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - Romain Chossart //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Soren Bramer Schmidt] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - Zak van der Merwe //! - Zachary Snyder //! - [Zach Peters] //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [Arlo (Hyena)]: https://asonix.dog/@asonix //! [Behnam Esfahbod]: https://github.com/behnam //! [Benjamin Manns]: https://www.benmanns.com/ //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Douglas Correa]: http://learnrust.io/ //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Evan Stoll]: https://github.com/evanjs //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Fabio Correa]: https://linkedin.com/in/feamcor //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Hugo Josefson]: https://www.hugojosefson.com //! [Jason Bowen]: https://twitter.com/jwbowen //! [Jeff May]: https://gitlab.com/jeffmay //! [Jendrik Illner]: https://www.jendrikillner.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [Joe Percy]: http://joetdc.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Malnormalulo]: https://twitter.com/Malnormalulo //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Michael Melanson]: https://www.michaelmelanson.net //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Soren Bramer Schmidt]: http://prisma.io/ //! [Stuart Hinson]: http://stuarth.github.io/ //! [Zach Peters]: https://github.com/zpeters //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) use std::ffi::{CStr, CString}; use std::fmt::{Display, Error, Formatter}; use libc::{c_char, c_float, c_int}; #[doc = include_str!("../../docs/e031-script.md")] pub struct Script; /// The simplest possible example of exposing Rust functions via a C FFI. #[no_mangle] pub extern "C" fn add_in_rust(a: c_int, b: c_int) -> c_int { a + b } /// Take two strings in and concatentate them without mutating either. /// /// This allocates a new string, which *must* be deallocated by calling the /// `free_rust_string` type exposed in this module. /// /// # Safety /// /// This is *only* valid when the first and second pointers are not null (which /// is checked) and when the char strings pointed to by the two pointers do not /// overlap! #[no_mangle] pub unsafe extern "C" fn concat_strings( first: *const c_char, second: *const c_char, ) -> *mut c_char { let (first, second) = unsafe { // Start by making sure the two strings are not null pointers (since C // APIs don't actually give us any help with this). assert!(!first.is_null()); assert!(!second.is_null()); // Then use `CString::from_ptr` to let Rust's own built-in smarts about // how to convert from a pointer to a `c_char` do the conversion // correctly. These are *not* the same as Rust `String`s, after all! ( CStr::from_ptr(first).to_bytes(), CStr::from_ptr(second).to_bytes(), ) }; CStr::from_bytes_with_nul(&[&first[0..first.len()], &second[0..second.len()], b"\0"].concat()) .expect("should be possible to construct a new `CStr` from existing `CStr`s") .to_owned() .into_raw() } /// Free any string allocated by Rust. /// /// # Safety /// /// This shows how you *could* allow an outside caller to free a Rust string. It /// is only safe to do if you guarantee there are no other references to it! #[no_mangle] pub unsafe extern "C" fn free_rust_string(to_free: *mut c_char) { // If the pointer is already `null`, we're done here. (Don't double `free`!) if to_free.is_null() { return; } // If the pointer is not already null, we take ownership of it again with // `from_raw` and then immediately free it by way of the inherent `Drop`. unsafe { let ptr = CString::from_raw(to_free); drop(ptr); } } /// A simple struct which we can expose to a C API. Note that it is `#[repr(C)]`! #[repr(C)] pub struct Point { /// x position -- made `pub` to indicate that we're exposing it to C! pub x: f32, /// y position -- made `pub` to indicate that we're exposing it to C! pub y: f32, } impl Point { fn translate(&mut self, by_x: f32, by_y: f32) { self.x += by_x; self.y += by_y; } } /// Expose an interface for C API callers to call the `Point` impl. /// /// # Safety /// /// This is only safe if there are no references to `point`! #[no_mangle] pub unsafe extern "C" fn point_translate(point: *mut Point, by_x: c_float, by_y: c_float) { let point = unsafe { assert!(!point.is_null()); &mut *point }; // Note that if this wasn't safe, because for some reason `c_float` did not // match `f32`, the compiler would tell us. point.translate(by_x, by_y); } /// A struct identical to `Point`, but which is *not* `#[repr(C)]`! /// /// The layout here is intentionally left in Rust's own representation, and we /// do *not* expose the internals in `e031.h`. pub struct OpaquePoint { x: f32, y: f32, } impl OpaquePoint { fn translate(&mut self, by_x: f32, by_y: f32) { self.x += by_x; self.y += by_y; } } impl Display for OpaquePoint { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { write!(f, "`{}, {}`", self.x, self.y) } } /// Expose an interface for C API callers to call the `OpaquePoint` impl. /// /// This implementation is *identical* to the implementation of the `Point` /// above. The only difference is that the C side doesn't get access to the /// internal structure of the type… which is we want. /// /// # Safety /// /// This is only safe if there are no references to `point`! #[no_mangle] pub unsafe extern "C" fn opaque_point_translate( point: *mut OpaquePoint, by_x: c_float, by_y: c_float, ) { let point = unsafe { assert!(!point.is_null()); &mut *point }; // Note that if this wasn't safe, because for some reason `c_float` did not // match `f32`, the compiler would tell us. point.translate(by_x, by_y); } #[no_mangle] pub extern "C" fn opaque_point_new(x: c_float, y: c_float) -> *mut OpaquePoint { Box::into_raw(Box::new(OpaquePoint { x, y })) } /// # Safety /// /// This is only safe if there are no references to `point`! #[no_mangle] pub unsafe extern "C" fn opaque_point_describe(point: *mut OpaquePoint) -> *mut c_char { let point = unsafe { assert!(!point.is_null()); &mut *point }; CString::new(format!("{}", point)) .expect("always safe to get `CString` from `String`") .into_raw() } /// Safely drops the `OpaquePoint` instance. /// /// # Safety /// /// This is only safe if there are no references to `point`! #[no_mangle] pub unsafe extern "C" fn opaque_point_free(point: *mut OpaquePoint) { if point.is_null() { return; } unsafe { drop(Box::from_raw(point)); }; } /// Demonstrate unions! Combines an `enum` and a `union` into a `struct` that /// acts mostly like a regular Rust `enum`. pub mod unions { /// Builds an instance of `Either`, a manually-managed "tagged union" type. /// /// If you read the body, you'll notice that we're not *helped* in any way /// by Rust like we are with normal `enum` types. pub fn demo_union() { // Here, we construct the type correctly. let either = Either::> { tag: Tag::Left, value: EitherValue { left: 42 }, }; // But notice that the compiler doesn't help us! Comment out the // following lines and see that it still *compiles* just fine... but is // very much *not* correct semantically: we have a `Left` tag with a // `right` value! // let bad_either = Either::> { // tag: Tag::Left, // value: EitherValue { right: Wrapped(42) }, // }; unsafe { match either { Either { tag: Tag::Left, value: EitherValue { left }, } => { dbg!(left); } Either { tag: Tag::Right, value: EitherValue { right }, } => { dbg!(right); } } } } /// For tagging the type in `Either`. See the body of `demo_union`. #[derive(Clone, Copy)] pub enum Tag { Left, Right, } /// A simple type designed to demo unions. See the body of `demo_union`. #[derive(Debug, Copy, Clone)] pub struct Wrapped(T); /// A union, to be used as the inner value for `Either`. pub union EitherValue { left: L, right: R, } /// Uses an `enum` and a `union` to get close to a regular Rust enum. /// /// Roughly, because the compiler won't check you for exhaustiveness, or /// even make sure you're using the tag and value pair the way you should! pub struct Either { pub tag: Tag, pub value: EitherValue, } } ================================================ FILE: src/includes/media-playback-speed.html ================================================ ================================================ FILE: src/interview/_1/mod.rs ================================================ //! Sean Griffin pub mod part_1; pub mod part_2; ================================================ FILE: src/interview/_1/part_1.rs ================================================ //! Sean Griffin on Rust, ORMs, and Web Frameworks //! //! - **Date:** February 15, 2016 //! - **Subject:** Rust, ORMs, and Web Frameworks //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/1/part_1.mp3 //! //! //! //! //! Notes //! ----- //! //! Chris chats with Sean Griffin about his programming background and initial //! experience with Rust, Rust's appeal, and what he's doing with Diesel and //! some of his plans for a new web framework in Rust. //! //! //! Links //! ----- //! //! - [Ruby on Rails][l1] //! - [Active Record][l2] //! - [Diesel][l3] //! + [GitHub][l4] //! + [Gitter][l5] //! - [The Bike Shed][l6] episodes which include talk of Rust and Diesel //! + [51: Is Sim City Still Running (with Steve Klabnik)][l7] //! + [49: A More Practical Haskell][l8] //! + [48: Is Everyone Trying Their Best?][l9] //! + [46: Don't Breath, Save the Planet][l10] //! + [44: It Won't Crash... It Might Crash][l11] //! + [39: Okay With Instability][l12] //! + [32: Bug for Bug Compatibility][l13] //! + [31: Oxidizing an ORM][l14] //! + [27: I've Got 29.97 Problems (and codecs are some)][l15] //! + [23: Why Did They Call It Rust?][l16] //! - [_Maybe Haskell_][l17] //! //! [l1]: http://rubyonrails.org //! [l2]: http://guides.rubyonrails.org/active_record_basics.html //! [l3]: http://diesel.rs //! [l4]: https://github.com/sgrif/diesel //! [l5]: https://gitter.im/sgrif/diesel //! [l6]: http://bikeshed.fm //! [l7]: http://bikeshed.fm/51 //! [l8]: http://bikeshed.fm/49 //! [l9]: http://bikeshed.fm/48 //! [l10]: http://bikeshed.fm/46 //! [l11]: http://bikeshed.fm/44 //! [l12]: http://bikeshed.fm/39 //! [l13]: http://bikeshed.fm/32 //! [l14]: http://bikeshed.fm/31 //! [l15]: http://bikeshed.fm/27 //! [l16]: http://bikeshed.fm/23 //! [l17]: https://gumroad.com/l/maybe-haskell //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Chris Palmer //! - [Derek Morr][s3] //! - Hamza Sheikh //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - Ralph Giles ("rillian") //! - reddraggone9 //! - Ryan Ollos //! - [William Roe][s11] //! //! [s3]: https://twitter.com/derekmorr //! [s11]: http://willroe.me //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! //! Follow //! ------ //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/interview/_1/part_2.rs ================================================ //! Sean Griffin on type systems and hopes for Rust's future //! //! - **Date:** February 25, 2016 //! - **Subject:** Type system strengths and weaknesses, and the weird corners //! of Rust (with some hopes for its future) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/1/part_2.mp3 //! //! //! //! //! Notes //! ----- //! //! Chris chats with Sean Griffin about the tradeoffs between mental overhead //! and type safety, the expressiveness of different type systems, and some of //! the places where Rust currently falls down. //! //! //! ### Corrigenda //! //! Sean noted he could be wrong about `IEnumerable` not having a `Sum` //! method in C♯, and post-show research indicated that he was (it's possible it //! was added after he had stopped doing .NET work, of course). See the //! [documentation][c1] for details on how `IEnumerable.Sum` it behaves in C♯ //! if you're curious. //! //! As a related note, I (Chris) have done a little bit of digging on C♯ in the //! interval and it's fair to say that while a lot of the "ceremony" involved in //! writing C♯ is annoying, it's much more than just a "slightly nicer Java", //! and indeed is a much nicer language than my previous, limited exposure had //! led me to believe. It's no Rust or F♯, but its type system is substantially //! more capable than Java's. //! //! [c1]: https://msdn.microsoft.com/library/bb919210(v=vs.90).aspx //! //! //! Links //! ----- //! //! - fmap //! + [Discussion of `fmap` with `Optional` in Swift][l1] //! + [In Haskell][l2] //! - Rust: //! + [Trait objects][l3] //! + [Specialization RFC][l4] //! * [Implementation][l5] //! - [Diesel][l6] //! //! [l1]: https://robots.thoughtbot.com/functional-swift-for-dealing-with-optional-values //! [l2]: http://learnyouahaskell.com/functors-applicative-functors-and-monoids //! [l3]: https://doc.rust-lang.org/book/trait-objects.html //! [l4]: https://github.com/rust-lang/rfcs/pull/1210 //! [l5]: https://github.com/rust-lang/rust/issues/31844 //! [l6]: https://github.com/sgrif/diesel //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Chris Palmer //! - [Derek Morr][s3] //! - Hamza Sheikh //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - Ralph Giles ("rillian") //! - reddraggone9 //! - Ryan Ollos //! - [William Roe][s11] //! //! [s3]: https://twitter.com/derekmorr //! [s11]: http://willroe.me //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! //! //! Follow //! ------ //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/interview/_2/mod.rs ================================================ //! Raph Levien pub mod part_1; pub mod part_2; ================================================ FILE: src/interview/_2/part_1.rs ================================================ //! Raph Levien on using Rust to build the Xi editor //! //! - **Date:** June 24, 2016 //! - **Subject:** The Xi Editor project as a window into complex data //! structures, memory management, and the Unix philosophy. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/2/part_1.mp3 //! //! //! //! //! Notes //! ----- //! //! Chris chats with Raph Levien about his background in software development, //! what attracted him to Rust, and how he's using Rust to build the Xi Editor, //! a project which aims to be the fastest text editor out there, with native //! user interfaces and a Rust text engine. //! //! //! Links //! ----- //! //! - Past work: //! //! + [GIMP] //! + [GTK] //! + [GhostScript] //! + [Google Web Fonts] //! + [font-rs] //! //! - Current projects: //! //! + [pulldown-cmark] //! + [Xi Editor] //! //! - [fuzz testing] //! //! - [sanitizers] //! //! - [FreeType] //! //! - [HarfBuzz] //! //! - [ICU] //! //! - Ropes //! //! + [Wikipedia summary] //! + [original paper] //! - ["log n operation"], or *O(log n)* //! //! + [Big O notation] //! - Rust: //! //! + [`Arc`] //! + [`RefCell`] //! + [`Borrow`] //! + [`AsRef`] //! - Rust libraries //! //! + Crossbeam: [source][Crossbeam source] | [docs][Crossbeam docs] //! + Rayon: [source][Rayon source] | [docs][Rayon docs] //! //! - [Unix philosophy] //! //! > The Unix philosophy emphasizes building simple, short, clear, //! > modular, and extensible code that can be easily maintained and //! > repurposed by developers other than its creators. The Unix philosophy //! > favors composability as opposed to monolithic design. //! //! [GIMP]: http://www.gimp.org //! [GTK]: http://gtk.org //! [GhostScript]: http://www.ghostscript.com //! [Google Web Fonts]: https://fonts.google.com //! [font-rs]: https://github.com/google/font-rs //! [pulldown-cmark]: https://github.com/google/pulldown-cmark //! [Xi Editor]: https://github.com/google/xi-editor //! [fuzz testing]: https://en.wikipedia.org/wiki/Fuzz_testing //! [sanitizers]: http://developers.redhat.com/blog/2014/12/02/address-and-thread-sanitizers-gcc/ //! [FreeType]: https://www.freetype.org //! [HarfBuzz]: https://www.freedesktop.org/wiki/Software/HarfBuzz/ //! [ICU]: http://site.icu-project.org //! [Wikipedia summary]: https://en.wikipedia.org/wiki/Rope_%28data_structure%29 //! [original paper]: http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.14.9450&rep=rep1&type=pdf //! ["log n operation"]: http://stackoverflow.com/questions/2307283/what-does-olog-n-mean-exactly //! [Big O notation]: https://en.wikipedia.org/wiki/Big_O_notation //! [`Arc`]: http://doc.rust-lang.org/std/sync/struct.Arc.html //! [`RefCell`]: http://doc.rust-lang.org/std/cell/struct.RefCell.html //! [`Borrow`]: http://doc.rust-lang.org/std/borrow/trait.Borrow.html //! [`AsRef`]: http://doc.rust-lang.org/std/convert/trait.AsRef.html //! [Crossbeam source]: https://github.com/aturon/crossbeam //! [Crossbeam docs]: http://aturon.github.io/crossbeam-doc/crossbeam/ //! [Rayon source]: https://github.com/nikomatsakis/rayon //! [Rayon docs]: http://nikomatsakis.github.io/rayon/rayon/ //! [Unix philosophy]: https://en.wikipedia.org/wiki/Unix_philosophy //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - [Chris Palmer] //! - [Daniel Collin] //! - [Derek Morr] //! - Doug Reeves //! - Hamza Sheikh //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - [Pascal Hertleif] //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - Raph Levien //! - reddraggone9 //! - Ryan Ollos //! - Vesa Kaihlavirta //! - [William Roe] //! //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/interview/_2/part_2.rs ================================================ //! Raph Levien on Rust's current strengths and places it can improve //! //! - **Date:** July 4, 2016 //! - **Subject:** Using Rust for prototyping and exploring computer science //! problems, and places where Rust can improve going forward. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/2/part_2.mp3 //! //! //! //! //! Notes //! ----- //! //! Chris chats with Raph Levien about what inspired him to build a text editor, //! as well as about where the rough edges in the Rust development story are //! today, and how we might improve them going forward. //! //! //! Links //! ----- //! //! - Rust/Ruby bridge: Helix //! + [blog post] //! + [GitHub] //! - [Rust Bridge project] //! - Ropes //! + [original paper] //! + [Rust implementation] //! + [C++ implementation] //! - Yehuda Katz on Code Newbie //! + [Creating Ember JS - Part I] //! + [Creating Ember JS - Part II] //! - [Rust and Swift (xi): Hopes for the next generation of systems programming.][rust-swift-xi] //! //! [blog post]: http://blog.skylight.io/introducing-helix/ //! [GitHub]: https://github.com/rustbridge/helix //! [Rust Bridge project]: https://github.com/rustbridge //! [original paper]: https://www.cs.rit.edu/usr/local/pub/jeh/courses/QUARTERS/FP/Labs/CedarRope/rope-paper.pdf //! [Rust implementation]: https://github.com/google/xi-editor/tree/master/rust/rope //! [C++ implementation]: https://github.com/ivmai/bdwgc/ //! [Creating Ember JS - Part I]: http://www.codenewbie.org/podcast/creating-emberjs-part-i //! [Creating Ember JS - Part II]: http://www.codenewbie.org/podcast/creating-emberjs-part-ii //! [rust-swift-xi]: http://www.chriskrycho.com/2016/rust-and-swift-xi.html //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - [Chris Palmer] //! - [Daniel Collin] //! - [Derek Morr] //! - Doug Reeves //! - Hamza Sheikh //! - [Jakub "Limeth" Hlusička] //! - Keith Gray //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - Michael Clayton //! - [Pascal Hertleif] //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - Raph Levien //! - reddraggone9 //! - Ryan Ollos //! - Vesa Kaihlavirta //! - [William Roe] //! //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/interview/_3.rs ================================================ //! Carol (Nichols || Goulding) //! //! - **Date:** September 30, 2016 //! - **Subject:** Learning Rust, teaching Rust, and building community //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/3.mp3 //! //! //! //! //! Notes //! ----- //! //! Chris talks with Carol (Nichols || Goulding), a Rust community team member, co-author of //! the first major revision of _The Rust Programming Language_, and co-founder //! of the first Rust consultancy. //! //! Links //! ----- //! //! - [XSLT (XML Style Sheet Transformations)][XSLT] //! - [Rspec] //! - [Rails] //! - [Think Through Math] — remedial math tutoring app built with Rails //! - [Rust for Rubyists] //! - [_The Rust Programming Language_][TRPL] //! - [Julia Evans] //! + [RustConf 2016 keynote][keynote] //! - [_Rust by Example_][RBE] //! - [Rustlings] //! - Sass //! + [language][sass-lang] //! + [Carol's in-progress implementation][sass-impl] //! - [#rust-community][IRC] — open meetings at 4pm UTC every Wednesday, with //! [minutes available online][minutes] //! - [first Rust community survey][survey] //! - [Rust community on GitHub][community] //! - [new version of the book on GitHub][TRPL update] — *you* can help, and //! especially if you're new, because Steve and Carol both need input to deal //! with the "familiarity"/["curse of knowledge"] problem //! - ownership and borrowing chapters //! - [RustConf] //! - [RustFest] //! - [Rust Belt Rust] — October 27–28, 2016. _Don't forget to use code //! **newrustacean** to get 20% off of your registration cost!_ //! - [Integer32] //! - [Panoptix] – nickel-jwt-session: [crate] | [docs] | [source] //! - [Jake Goulding on Stack Overflow][so] //! - [Friends of the Tree] //! - [Friends of the Forest] //! - [_Working Effectively With Legacy Code_][WEWLC] //! - Tilde //! - [_The C Programming Language_][TCPL] -- the book Carol compared _The Rust //! Programming Language_ to in terms of its responsibilities, and also one of //! the books from which Chris learned C. //! //! [XSLT]: https://developer.mozilla.org/en-US/docs/Web/XSLT //! [Rspec]: http://rspec.info //! [Rails]: http://rubyonrails.org //! [Think Through Math]: https://www.thinkthroughmath.com //! [Rust for Rubyists]: https://github.com/steveklabnik/rust_for_rubyists //! [TRPL]: https://doc.rust-lang.org/book/ //! [Julia Evans]: http://jvns.ca //! [keynote]: http://jvns.ca/blog/2016/09/11/rustconf-keynote/ //! [RBE]: http://rustbyexample.com //! [Rustlings]: https://github.com/carols10cents/rustlings //! [sass-lang]: http://sass-lang.com //! [sass-impl]: https://github.com/carols10cents/sassers //! [IRC]: https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-community //! [minutes]: https://github.com/rust-community/team/tree/master/meeting-minutes //! [survey]: https://blog.rust-lang.org/2016/06/30/State-of-Rust-Survey-2016.html //! [community]: https://github.com/rust-community //! [TRPL update]: http://rust-lang.github.io/book/ //! ["curse of knowledge"]: https://en.wikipedia.org/wiki/Curse_of_knowledge //! [RustConf]: http://rustconf.com //! [RustFest]: http://www.rustfest.eu //! [Rust Belt Rust]: http://www.rust-belt-rust.com //! [Integer32]: http://www.integer32.com //! [Panoptix]: http://www.panoptix.co.za/ //! [crate]: https://crates.io/crates/nickel-jwt-session //! [docs]: https://docs.rs/nickel-jwt-session/ //! [source]: https://github.com/kaj/nickel-jwt-session //! [so]: http://stackoverflow.com/cv/jakegoulding //! [Friends of the Tree]: https://github.com/rust-lang/rust-wiki-backup/blob/master/Doc-friends-of-the-tree.md //! [Friends of the Forest]: https://github.com/rust-community/team/issues/51 //! [WEWLC]: http://www.alibris.com/booksearch?keyword=working%20effectively%20with%20legacy%20code //! [TCPL]: http://www.alibris.com/The-C-Programming-Language-Brian-Kernighan/book/875968 //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Cameron Mochrie //! - [Chris Palmer] //! - [Daniel Collin] //! - [Derek Morr] //! - Doug Reeves //! - Hamza Sheikh //! - [Jakub "Limeth" Hlusička] //! - [Jupp Müller] //! - Keith Gray //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Matthew Piziak //! - Micael Bergeron //! - Nils Tekampe //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - Raph Levien //! - reddraggone9 //! - Ryan Ollos //! - Sean Jensen-Gray //! - Steven Murawski //! - Vesa Kaihlavirta //! - [William Roe] //! //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/interview/_4/mod.rs ================================================ //! Jonathan Turner //! //! Jonathan's history, his work on Rust, and his work on Servo. pub mod part_1; pub mod part_2; pub mod part_3; ================================================ FILE: src/interview/_4/part_1.rs ================================================ //! Part 1: Getting to Rust //! //! - **Date:** April 30, 2017 //! - **Subject:** Background, TypeScript, coming to Rust, and how helpful the //! Rust community can be. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/4/part_1.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! On Jonathan's programming backstory: //! //! - [TI-99/4A] //! - [Commodore 64] //! - [Cray] //! + [Chapel] //! - [TypeScript] //! - [Yehuda Katz] //! - [ECMAScript Language Committee] //! - [Data locality] //! - [CPPCast] //! - [BASIC] //! - [Pascal] //! - [Ultima] //! //! [TI-99/4A]: https://en.wikipedia.org/wiki/Texas_Instruments_TI-99/4A //! [Commodore 64]: https://en.wikipedia.org/wiki/Commodore_64 //! [Cray]: http://www.cray.com //! [Chapel]: http://chapel.cray.com //! [TypeScript]: http://www.typescriptlang.org //! [Yehuda Katz]: http://yehudakatz.com //! [ECMAScript Language Committee]: https://www.ecma-international.org/memento/TC39.htm //! [Data locality]: https://en.wikipedia.org/wiki/Locality_of_reference //! [CPPCast]: http://cppcast.com //! [BASIC]: https://en.wikipedia.org/wiki/BASIC //! [Pascal]: https://en.wikipedia.org/wiki/Pascal_(programming_language) //! [Ultima]: https://en.wikipedia.org/wiki/Ultima_%28series%29 //! //! //! After the transition to working on Rust full-time: //! //! - Improving the error messages— //! + [design issue] //! + Jonathan's personal blog post ["Helping with the Rust Errors"] //! + Official Rust blog post announcing and describing the feature, //! ["Shape of Errors to Come"] //! + [Elm] //! + [error list issue] //! //! [design issue]: https://github.com/rust-lang/rust/issues/33240 //! ["Helping with the Rust Errors"]: http://www.jonathanturner.org/2016/08/helping-out-with-rust-errors.html //! ["Shape of Errors to Come"]: https://blog.rust-lang.org/2016/08/10/Shape-of-errors-to-come.html //! [Elm]: http://elm-lang.org //! [error list issue]: https://github.com/rust-lang/rust/issues/35233 //! //! //! Sponsors //! -------- //! //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - Ben Whitley //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Christopher Giffard] //! - Dan Abrams //! - [Daniel Collin] //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Jakub "Limeth" Hlusička] //! - Jonathan Turner //! - Jordan Henderson //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Lachlan Collins //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Raph Levien //! - reddraggone9 //! - Steven Murawski //! - [Stuart Hinson] //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Warren Harper //! - [William Roe] //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/interview/_4/part_2.rs ================================================ //! Part 2: Making Rust Better //! //! - **Date:** May 30, 2017 //! - **Subject:** Rust as the fusion of systems and high-level programming //! languages, and the RLS. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/4/part_2.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! - The [survey] //! - Language adoption: //! + [Guido van Rossum] and [Python] //! + [Matz (Yukihiro Matsumoto)][Matz] and [Ruby] //! + [Dart] //! //! [survey]: https://blog.rust-lang.org/2016/06/30/State-of-Rust-Survey-2016.html //! [Guido van Rossum]: https://en.wikipedia.org/wiki/Guido_van_Rossum //! [Python]: https://www.python.org //! [Matz]: https://en.wikipedia.org/wiki/Yukihiro_Matsumoto //! [Ruby]: https://www.ruby-lang.org/en/ //! [Dart]: https://www.dartlang.org //! //! Building the Rust Language Service: //! //! - [Racer] //! - [rustw] //! - [Language Server Protocol][lsp] //! - [Demo at RustConf 2016] //! - [Anders Hejlsberg] – designer or lead developer of [Turbo Pascal], //! [Delphi], [C#], and [TypeScript] //! - [Serde] //! - [Roadmap GitHub Project] //! - Language Server Protocol plugins //! + [RLS reference VS Code plugin] //! + Kalita Alexey's [vscode-rust] //! + [langserver.org] //! - [The 2017 Rust Roadmap] //! + [Improved match ergonomics around references] //! + [const generics] //! * [RFC #1931] //! //! [Racer]: https://github.com/phildawes/racer //! [rustw]: https://github.com/nrc/rustw //! [lsp]: https://github.com/Microsoft/language-server-protocol //! [Demo at RustConf 2016]: https://youtu.be/pTQxHIzGqFI?t=42m5s //! [Anders Hejlsberg]: https://en.wikipedia.org/wiki/Anders_Hejlsberg //! [Turbo Pascal]: https://en.wikipedia.org/wiki/Turbo_Pascal //! [Delphi]: https://en.wikipedia.org/wiki/Delphi_(programming_language) //! [C#]: https://docs.microsoft.com/en-us/dotnet/articles/csharp/ //! [TypeScript]: http://www.typescriptlang.org //! [Serde]: https://serde.rs //! [Roadmap GitHub Project]: https://github.com/rust-lang-nursery/rls/projects/2 //! [RLS reference VS Code plugin]: https://github.com/jonathandturner/rls_vscode //! [vscode-rust]: https://github.com/editor-rs/vscode-rust //! [langserver.org]: http://langserver.org //! [The 2017 Rust Roadmap]: https://blog.rust-lang.org/2017/02/06/roadmap.html //! [Improved match ergonomics around references]: https://github.com/rust-lang/rust-roadmap/issues/24 //! [const generics]: https://internals.rust-lang.org/t/lang-team-minutes-const-generics/5090 //! [RFC #1931]: https://github.com/rust-lang/rfcs/pull/1931 //! //! //! Sponsors //! -------- //! //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - Ben Whitley //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Christopher Giffard] //! - Dan Abrams //! - [Daniel Collin] //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Jakub "Limeth" Hlusička] //! - Jonathan Turner //! - Jordan Henderson //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Lachlan Collins //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Raph Levien //! - reddraggone9 //! - Steven Murawski //! - [Stuart Hinson] //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Warren Harper //! - [William Roe] //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/interview/_4/part_3.rs ================================================ //! Part 3: Smoothing the Rust dev story //! //! - **Date:** June 17, 2017 //! - **Subject:** Future work on the RLS, in Rust itself, and in Servo. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/4/part_3.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! Building the Rust Language Service: //! //! - Language Server Protocol plugins //! + [RLS reference VS Code plugin] //! + Kalita Alexey's [vscode-rust] //! + [langserver.org] //! - [The 2017 Rust Roadmap] //! + [Improved match ergonomics around references] //! + [const generics] //! * [RFC #1931] //! //! [RLS reference VS Code plugin]: https://github.com/jonathandturner/rls_vscode //! [vscode-rust]: https://github.com/editor-rs/vscode-rust //! [langserver.org]: http://langserver.org //! [The 2017 Rust Roadmap]: https://blog.rust-lang.org/2017/02/06/roadmap.html //! [Improved match ergonomics around references]: https://github.com/rust-lang/rust-roadmap/issues/24 //! [const generics]: https://internals.rust-lang.org/t/lang-team-minutes-const-generics/5090 //! [RFC #1931]: https://github.com/rust-lang/rfcs/pull/1931 //! //! //! Working on Servo: //! //! - [Servo] //! + [Windows nightlies] //! - [LLVM] //! + Apple's use on their graphics pipeline: //! - [OpenGL] //! - [Metal] //! + [clang] //! + [Swift] //! - [Project Quantum] //! - [WebKit] //! + [KHTML] //! + [Safari] //! //! [Servo]: https://servo.org //! [Windows nightlies]: https://blog.servo.org/2017/04/13/windows/ //! [llvm]: http://llvm.org //! [OpenGL]: http://lists.llvm.org/pipermail/llvm-dev/2006-August/006497.html //! [Metal]: https://developer.apple.com/metal/metal-shading-language-specification.pdf //! [clang]: http://clang.llvm.org //! [swift]: https://swift.org //! [Project Quantum]: https://medium.com/mozilla-tech/a-quantum-leap-for-the-web-a3b7174b3c12 //! [WebKit]: https://webkit.org //! [KHTML]: https://en.wikipedia.org/wiki/KHTML //! [Safari]: https://www.apple.com/safari/ //! //! //! Sponsors //! -------- //! //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Ben Whitley //! - Benjamin Wasty //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Christopher Giffard] //! - Dan Abrams //! - [Daniel Collin] //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Jakub "Limeth" Hlusička] //! - Jonathan Turner //! - Jordan Henderson //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Lachlan Collins //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Warren Harper //! - [William Roe] //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/interview/diesel_1_0/mod.rs ================================================ //! Diesel 1.0, with Sean Griffin pub mod part_1; pub mod part_2; ================================================ FILE: src/interview/diesel_1_0/part_1.rs ================================================ //! Part 1: The past and present of Diesel //! //! - **Date:** January 13, 2018 //! - **Subject:** Growing Diesel's community, self-imposed technical //! challenges, and some of the ways Diesel has contributed to the Rust //! ecosystem. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/diesel_1_0/part_1.mp3 //! //! //! //! //! ## Show notes //! //! - [Sean's previous appearance on the show][sean-1] //! - Chat app options: //! - [IRC] //! - [Slack] //! - [Gitter] //! - [The Diesel Gitter room] //! - [Discord] //! - SQL back ends //! - [PostgreSQL] //! - [SQLite] //! - [MySQL] //! - [endianness] //! - [`byteorder` crate] //! - [object safety] //! - [trait object] //! - [Sean's RustConf talk] //! - [monomorphization] //! - [Custom derive and procedural macros] //! //! //! [sean-1]: https://www.newrustacean.com/show_notes/interview/_1/index.html //! [IRC]: https://en.wikipedia.org/wiki/Internet_Relay_Chat //! [Slack]: https://slack.com //! [Gitter]: https://gitter.im //! [Discord]: https://discordapp.com //! [The Diesel Gitter room]: https://gitter.im/diesel-rs/diesel //! [PostgreSQL]: https://www.postgresql.org //! [SQLite]: http://sqlite.org //! [MySQL]: http://mysql.com //! [endianness]: http://beej.us/guide/bgnet/html/multi/ipstructsdata.html#byteorder //! [`byteorder` crate]: https://crates.io/crates/byteorder //! [object safety]: https://huonw.github.io/blog/2015/01/object-safety/ //! [trait object]: https://doc.rust-lang.org/book/first-edition/trait-objects.html //! [Sean's RustConf talk]: https://www.youtube.com/watch?v=wxPehGkoNOw //! [monomorphization]: http://cglab.ca/~abeinges/blah/rust-reuse-and-recycle/#monomorphization //! [Custom derive and procedural macros]: https://doc.rust-lang.org/book/first-edition/procedural-macros.html //! //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - Guido Hoermann //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) /// Transcript – coming at some point! pub struct Script; ================================================ FILE: src/interview/diesel_1_0/part_2.rs ================================================ //! Part 2: The future of Diesel //! //! - **Date:** January 21, 2018 //! - **Subject:** Getting Diesel to 1.0, writing docs and exposing problems //! with the API, improving Diesel in the future, and thinking about API //! design for open source libraries in general. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/diesel_1_0/part_2.mp3 //! //! //! //! //! ## Show notes //! //! - [Macros 2.0] //! - The Bike Shed episodes on Diesel 0.99 and 1.0 //! - [126: Speaking of Compilers...] - where Sean talked about some of the same //! changes mentioned on the show here. //! - [135: A Series of Unfortunate Examples] - where Sean talks a bit more //! about his adventures writing docs for Diesel 1.0 (and the //! corresponding feature freeze). //! - [Generic associated types], which you may have heard of under the name //! "associated type constructors" //! - [Multitenancy] //! - [Library patterns: multiple levels of abstraction][lib] – Tomas Petricek //! on designing library abstractions with a 80%/14%/5%/1% structure. //! - [blanket implementations], [specialization], [coherence], and [the //! lattice rule] //! //! //! [Macros 2.0]: https://github.com/nrc/rfcs/blob/7dcb7374aee3281c261510ca5af53399a3df60f5/text/0000-macros.md //! [126: Speaking of Compilers...]: http://bikeshed.fm/126 //! [135: A Series of Unfortunate Examples]: http://bikeshed.fm/135 //! [Generic associated types]: https://github.com/rust-lang/rfcs/blob/master/text/1598-generic_associated_types.md //! [multitenancy]: https://en.wikipedia.org/wiki/Multitenancy //! [lib]: http://tomasp.net/blog/2015/library-layers/index.html //! [blanket implementations]: https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods //! [specialization]: https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md //! [coherence]: https://aturon.github.io/blog/2017/02/06/specialization-and-coherence/ //! [lattice rule]: https://rust-lang.github.io/rfcs/1210-impl-specialization.html#alternative-specialization-designs //! //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - Guido Hoermann //! - [Hans Fjällemark] //! - Hendrik Sollich //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) /// Transcript – coming at some point! pub struct Script; ================================================ FILE: src/interview/integer32.rs ================================================ //! Integer32: Carol Nichols || Goulding and Jake Goulding //! //! - **Date:** December 31, 2018 //! - **Subject:** Talking with Carol and Jake about _The Rust Programming //! Language_, _Rust in Motion_, and Rust Belt Rust. With a bonus discussion //! about the value of focusing on our kids over just building big businesses. //! - [**download mp3**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/integer32.mp3 //! //! //! //! Show Notes //! ---------- //! //! Things we mentioned on the show: //! //! - [the playground] //! - [Ferrous Systems] //! - Magical JSON: [QuickType] //! - EddyB’s company: [Lyken Software Solutions] //! - Integer32 blog: [“Tech Conference Budget Case Study: Rust Belt Rust 2018”] //! //! [the playground]: https://github.com/integer32llc/rust-playground //! [Ferrous Systems]: https://ferrous-systems.com //! [QuickType]: https://quicktype.io //! [Lyken Software Solutions]: https://lyken.rs //! [“Tech Conference Budget Case Study: Rust Belt Rust 2018”]: https://integer32.com/2018/11/29/2018-rust-belt-rust-finance-report.html //! //! //! Sponsors //! -------- //! //! Thanks to Manning for sponsoring this episode; don’t forget to grab some of //! their content at 40% off using the code `podnewrust18`! //! //! Thanks to Parity for sponsoring the show again. Go check out their [***Rust //! jobs***][parity]! //! //! [parity]: https://paritytech.io/jobs/ //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - [beaorn] //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Hewson //! - [Derek Morr] //! - Doug Reeves //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - [Fabio (decathorpe)] //! - Fábio Botelho //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - Jerome Froelich //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Marhee //! - Justin Ossevoort //! - Kai Yao //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - Michael Melanson //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Steffen Loen Sunde] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Zak van der Merwe //! - Zachary Snyder //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [beaorn]: https://github.com/beaorn //! [Behnam Esfahbod]: https://github.com/behnam //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Steffen Loen Sunde]: https://www.ntnu.edu/employees/steffen.sunde //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/interview/irr_2017/anna_liao.rs ================================================ //! Anna Liao //! //! - **Date:** December 20, 2017 //! - **Subject:** Anna's experience learning Rust while porting a Raspberry Pi //! Python project as part of the Increasing Rust’s Reach 2017 program. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/irr/anna_liao.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! - [Increasing Rust's Reach] //! - [Go] //! - [This Week In Rust] //! - [PyCon] //! - [Raspberry Pi] //! - [Sense HAT] //! - [PyCascades] //! - [Andrew Gallant (`burntsushi`)] //! + [ripgrep] //! - [RustBridge] //! - [exercism.io] //! - [the other Sense HAT Rust conversion] //! //! [Increasing Rust's Reach]: https://blog.rust-lang.org/2017/06/27/Increasing-Rusts-Reach.html //! [Go]: https://golang.org //! [This Week In Rust]: https://this-week-in-rust.org //! [PyCon]: http://www.pycon.org //! [Raspberry Pi]: https://www.raspberrypi.org //! [Sense HAT]: https://www.raspberrypi.org/products/sense-hat/ //! [PyCascades]: https://www.pycascades.com //! [Andrew Gallant (`burntsushi`)]: https://github.com/BurntSushi //! [ripgrep]: https://github.com/BurntSushi/ripgrep //! [RustBridge]: https://github.com/rust-community/rustbridge //! [exercism.io]: https://exercism.io //! [the other Sense HAT Rust conversion]: https://github.com/thejpster/pi-workshop-rs //! //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - Daniel P. Clark //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) /// Transcript coming soon! pub struct Transcript; ================================================ FILE: src/interview/irr_2017/lee_baillie.rs ================================================ //! Lee Baillie //! //! - **Date:** December 26, 2017 //! - **Subject:** Lee's experience designing a new website for Rust. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/irr/lee_baillie.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! - [Increasing Rust's Reach] //! - [Ember] //! - [Rails] //! - Talks //! + [at RustConf] \(as Liz Baillie) //! + [at RustFest Kyiv] \(as Liz Baillie) //! + [comparing Rust and Ruby at a meetup][meetup] //! - [Sinatra] //! - [Helix] //! - [the Slackbot framework] //! //! [Increasing Rust's Reach]: https://blog.rust-lang.org/2017/06/27/Increasing-Rusts-Reach.html //! [Ember]: https://emberjs.com //! [Rails]: http://rubyonrails.org //! [at RustConf]: https://www.youtube.com/watch?v=Ce6ppwgF4SA //! [at RustFest Kyiv]: https://www.youtube.com/watch?v=iF-FgJvDl6w&list=PL85XCvVPmGQhvs1Rnet_24B-AI3YSM2YG&index=2 //! [meetup]: https://www.youtube.com/watch?v=vDMZQzNQlXE&list=PLclEcT4yxER5GtZMe7feRdAwv-DLynsZt&index=1 //! [Sinatra]: http://sinatrarb.com //! [Helix]: http://usehelix.com //! [the Slackbot framework]: https://github.com/tildeio/slackathon //! //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - Daniel P. Clark //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) /// Transcript coming soon! pub struct Transcript; ================================================ FILE: src/interview/irr_2017/matt_gathu.rs ================================================ //! Matt Gathu //! //! - **Date:** December 30, 2017 //! - **Subject:** Matt's experience porting wget to Rust. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/irr/matt_gathu.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! - [Rosetta Code] //! - [wget] //! - [Matt's Rust implementation][rget] //! - Matt's blog posts //! - [Writing a Command Line Tool in Rust][cli] //! - [Testing a Rust Command Line Tool][test-cli] //! - Rust Nairobi //! - [Meetup] //! - [@RustNairobi] //! //! [Rosetta Code]: https://rosettacode.org/wiki/Category:Programming_Tasks //! [wget]: https://www.gnu.org/software/wget/ //! [rget]: https://github.com/mattgathu/duma //! [cli]: http://mattgathu.github.io/writing-cli-app-rust/ //! [test-cli]: http://mattgathu.github.io/testing-rust-cli-apps/ //! [Meetup]: https://www.meetup.com/Rust-Nairobi/ //! [@RustNairobi]: https://twitter.com/RustNairobi //! //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - Daniel P. Clark //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) /// Transcript coming soon! pub struct Transcript; ================================================ FILE: src/interview/irr_2017/mod.rs ================================================ //! Increasing Rust's Reach 2017 //! //! For background on the Increasing Rust's Reach program, see [this blog post]! //! //! [this blog post]: https://blog.rust-lang.org/2017/06/27/Increasing-Rusts-Reach.html pub mod anna_liao; pub mod lee_baillie; pub mod matt_gathu; ================================================ FILE: src/interview/mod.rs ================================================ //! Interviews: hearing from people around the Rust community! pub mod _1; pub mod _2; pub mod _3; pub mod _4; pub mod diesel_1_0; pub mod integer32; pub mod irr_2017; pub mod rbr_2017; ================================================ FILE: src/interview/rbr_2017/andrew_hobden.rs ================================================ //! Andrew Hobden //! //! - **Date:** December 13, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/andrew_hobden.mp3 //! //! #[doc = include_str!("../../../docs/rbr_2017/andrew-hobden.md")] pub struct Transcript; ================================================ FILE: src/interview/rbr_2017/anthony_deschamps.rs ================================================ //! Anthony Deschamps //! //! - **Date:** November 13, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/anthony_deschamps.mp3 //! //! #[doc = include_str!("../../../docs/rbr_2017/anthony-deschamps.md")] pub struct Transcript; ================================================ FILE: src/interview/rbr_2017/arun_kulshreshthra.rs ================================================ //! Arun Kulshreshtha //! //! - **Date:** November 14, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/arun_kulshreshthra.mp3 //! //! #[doc = include_str!("../../../docs/rbr_2017/arun-kulshreshtha.md")] pub struct Transcript; ================================================ FILE: src/interview/rbr_2017/ben_beckwith.rs ================================================ //! Ben Beckwith //! //! - **Date:** December 14, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/ben_beckwith.mp3 //! //! ================================================ FILE: src/interview/rbr_2017/ben_striegel.rs ================================================ //! Ben Striegel //! //! - **Date:** December 10, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/ben_striegel.mp3 //! //! #[doc = include_str!("../../../docs/rbr_2017/ben-striegel.md")] pub struct Transcript; ================================================ FILE: src/interview/rbr_2017/colin_dean.rs ================================================ //! Colin Dean //! //! - **Date:** November 11, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/colin_dean.mp3 //! //! #[doc = include_str!("../../../docs/rbr_2017/colin-dean.md")] pub struct Transcript; ================================================ FILE: src/interview/rbr_2017/esty_thomas.rs ================================================ //! Esty Thomas //! //! - **Date:** December 7, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/esty_thomas.mp3 //! //! ================================================ FILE: src/interview/rbr_2017/holden_marcsisin.rs ================================================ //! Holden Marcsisin //! //! - **Date:** December 9, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/holden_marcsisin.mp3 //! //! #[doc = include_str!("../../../docs/rbr_2017/holden-marcsisin.md")] pub struct Transcript; ================================================ FILE: src/interview/rbr_2017/jess_saxeter.rs ================================================ //! Jess Saxeter //! //! - **Date:** November 19, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/jess_saxeter.mp3 //! //! #[doc = include_str!("../../../docs/rbr_2017/jess-saxeter.md")] pub struct Transcript; ================================================ FILE: src/interview/rbr_2017/katie_nolan.rs ================================================ //! Katie Nolan //! //! - **Date:** December 15, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/katie_nolan.mp3 //! //! ================================================ FILE: src/interview/rbr_2017/matthias_endler.rs ================================================ //! Matthias Endler //! //! - **Date:** December 11, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/matthias_endler.mp3 //! //! ================================================ FILE: src/interview/rbr_2017/mod.rs ================================================ //! Micro-interviews from Rust Belt Rust 2017 //! //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Anton Van Moere //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - [Charlie Egan] //! - Chris Jones //! - Christian Schwarz //! - [Chris Palmer] //! - Dan Abrams //! - [Daniel Collin] //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Bettcher //! - Matthew Brenner //! - Matthew Piziak //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Peter Zuidhoek //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - Sam Whited //! - [Sebastián Ramírez Magrí] //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - [William Roe] //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: https://twitter.com/daniel_collin //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) pub mod andrew_hobden; pub mod anthony_deschamps; pub mod arun_kulshreshthra; pub mod ben_beckwith; pub mod ben_striegel; pub mod colin_dean; pub mod esty_thomas; pub mod holden_marcsisin; pub mod jess_saxeter; pub mod katie_nolan; pub mod matthias_endler; pub mod parry_wilcox; pub mod pete_lyons; pub mod thomas_gideon; pub mod tom_kriezkowski; ================================================ FILE: src/interview/rbr_2017/parry_wilcox.rs ================================================ //! Parry Wilcox //! //! - **Date:** December 12, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/parry_wilcox.mp3 //! //! ================================================ FILE: src/interview/rbr_2017/pete_lyons.rs ================================================ //! Pete Lyons //! //! - **Date:** November 18, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/pete_lyons.mp3 //! //! #[doc = include_str!("../../../docs/rbr_2017/pete-lyons.md")] pub struct Transcript; ================================================ FILE: src/interview/rbr_2017/thomas_gideon.rs ================================================ //! Thomas Gideon //! //! - **Date:** December 6, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/thomas_gideon.mp3 //! //! ================================================ FILE: src/interview/rbr_2017/tom_kriezkowski.rs ================================================ //! Tom Kriezkowski //! //! - **Date:** November 26, 2017 (recorded October 27, 2017) //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/interview/rbr/tom_kriezkowski.mp3 //! //! ================================================ FILE: src/lib.rs ================================================ //! Show notes //! //! Read the show notes, as well as fairly detailed comments on all the code //! samples referenced in the show. //! //! Yes, this is a slightly crazy way of building a show notes site for a //! podcast. See [e001: Document all the things!][e001] for more details. //! //! [e001]: /src/show_notes/e001.rs.html // Set the crate-level HTML rendering rules for the documentation. #![doc( html_logo_url = "https://newrustacean.com/podcast.png", html_favicon_url = "https://newrustacean.com/favicon.ico", html_root_url = "https://newrustacean.com/" )] // Enable access to the benchmarking functionality. Note that with this present, // we require using nightly Rust (as of 1.5). #![feature(test)] // *Many* items are unused, because they exist only to be demo'd. #![allow(dead_code)] // This statement gives us access to the `test` crate for benchmarking. extern crate test; // Make the show notes public. pub mod e000; pub mod e001; pub mod e002; pub mod e003; pub mod e004; pub mod e005; pub mod e006; pub mod e007; pub mod e008; pub mod e009; // We need to include `#[macro_use]` so that the macro will be exported for // other crates to use---or, in our case, to be visible in the docs/show notes. #[macro_use] pub mod e010; pub mod e011; pub mod e012; pub mod e013; pub mod e014; pub mod e015; pub mod e016; pub mod e017; pub mod e018; pub mod e019; pub mod e020; pub mod e021; pub mod e022; pub mod e023; pub mod e024; pub mod e025; pub mod e026; pub mod e027; pub mod e028; pub mod e029; pub mod e030; pub mod e031; pub mod bonus; pub mod cysk; pub mod interview; pub mod meta; pub mod news; ================================================ FILE: src/meta/_1.rs ================================================ //! Slowing Down //! //! - **Date:** November 12, 2016 //! - **Subject:** Avoiding burnout by taking it a little easier. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/meta/1.mp3 //! //! //! //! Sometimes, the way a podcast stays in existence is by coming out less often. //! That's what's happening here. //! //! # Links //! //! - [lightning-rs] //! - [Pelican] //! - [Hugo] //! - [Jekyll] //! - [Static Site Generators]: The definitive listing of Static Site //! Generators — all 445 of them! //! //! [lightning-rs]: https://github.com/chriskrycho/lightning-rs //! [Pelican]: http://getpelican.com //! [Hugo]: https://gohugo.io //! [Jekyll]: https://jekyllrb.com //! [Static Site Generators]: https://staticsitegenerators.net //! //! # Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! # Follow //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/meta/_2.rs ================================================ //! Two Milestones //! //! - **Date:** September 25, 2017 //! - **Subject:** Two years and fifty episodes of New Rustacean—time to //! celebrate with stickers and shirts! //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/meta/2.mp3 //! //! //! //! //! Links //! ----- //! //! - [JavaScript to Elm] //! - [Idris] //! - [Elixir] //! //! [JavaScript to Elm]: http://jstoelm.com //! [Idris]: http://www.idris-lang.org //! [Elixir]: http://www.elixir-lang.org //! //! ### Shirts //! //! [**Get them here!**][shirts] – available till Oct 9, 2017 at 8:00 PM EDT. //! //! [shirts]: https://cottonbureau.com/products/new-rustacean-2017 //! //! //! //! //! //! //! //! //! //! //! //! //! //! //! //! //! //! //! //! //! //! //! //!
    item/styleWomen'sMen's
    hoodie
    "heavy metal" shirt
    "heather white" t-shirt
    //! //! ### Stickers //! //! //! //! //! //! //! //! //! //! //! //! //!
    Die-cutCircular
    //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - Dan Abrams //! - [Daniel Collin] //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthew Piziak //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Warren Harper //! - [William Roe] //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: https://twitter.com/daniel_collin //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/meta/_3.rs ================================================ //! Happy Coding! //! //! - **Date:** May 27, 2019 //! - **Subject:** A story and a dream (and the promise of Rust): the final //! episode of New Rustacean! //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/meta/3.mp3 //! [script]: https://newrustacean.com/show_notes/meta/_3/struct.script //! //! //! //! Show Notes //! ---------- //! //! - [Rust by Example] //! - [Winning Slowly] //! - [Mass Affection] //! - [buttondown.email/rewrite] //! - [patreon.com/chriskrycho] //! //! [Rust by Example]: https://doc.rust-lang.org/stable/rust-by-example/ //! [Winning Slowly]: https://winningslowly.org //! [Mass Affection]: https://massaffection.com //! [patreon.com/chriskrycho]: https://patreon.com/chriskrycho //! [buttondown.email/rewrite]: https://buttondown.email/rewrite //! //! Sponsors //! -------- //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Lozada //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - Arlen Haftevani //! - [Arlo (Hyena)] //! - Arun Kulshreshtha //! - [Behnam Esfahbod] //! - [Benjamin Manns] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Cat Dad //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Christoffer Ceutz //! - Cristian Paul //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Carroll //! - David Hewson //! - [Derek Morr] //! - Dominic Cooney //! - Doug Reeves //! - [Douglas Correa] //! - Edmund Kump //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - [Evan Stoll] //! - [Fabio (decathorpe)] //! - [Fabio Correa] //! - Freeman P. Pascal //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - Hoàng Đức Hiếu //! - [Hugo Josefson] //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - [Jason Bowen] //! - [Jeff May] //! - [Jendrik Illner] //! - Jerome Froelich //! - JockeTF //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - Jonah //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Mou //! - Joseph Schrag //! - [Joe Percy] //! - Justin Ossevoort //! - Kai Yao //! - Kazutaka Mise //! - Keith Gray //! - Kilian Rault //! - Kyle //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Malnormalulo] //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - [Michael Melanson] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Oladapo Fadeyi //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - Romain Chossart //! - [Ryan Blecher] //! - [Ryan Osial] //! - Satoshi Yoshikawa //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Soren Bramer Schmidt] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Sven Huster //! - Tim Brooks //! - Tim Small //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - Zak van der Merwe //! - Zachary Snyder //! - [Zach Peters] //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [Arlo (Hyena)]: https://asonix.dog/@asonix //! [Behnam Esfahbod]: https://github.com/behnam //! [Benjamin Manns]: https://www.benmanns.com/ //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Douglas Correa]: http://learnrust.io/ //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Evan Stoll]: https://github.com/evanjs //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Fabio Correa]: https://linkedin.com/in/feamcor //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Hugo Josefson]: https://www.hugojosefson.com //! [Jason Bowen]: https://twitter.com/jwbowen //! [Jeff May]: https://gitlab.com/jeffmay //! [Jendrik Illner]: https://www.jendrikillner.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [Joe Percy]: http://joetdc.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Malnormalulo]: https://twitter.com/Malnormalulo //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Michael Melanson]: https://www.michaelmelanson.net //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Soren Bramer Schmidt]: http://prisma.io/ //! [Stuart Hinson]: http://stuarth.github.io/ //! [Zach Peters]: https://github.com/zpeters //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/meta-3.md")] pub struct Script; ================================================ FILE: src/meta/mod.rs ================================================ //! Meta episodes: content about the show itself. pub mod _1; pub mod _2; pub mod _3; ================================================ FILE: src/news/_1.rs ================================================ //! One year and counting //! //! - **Date:** May 31, 2016 //! - **Subject:** A year in, Rust is changing fast but still stable. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/1.mp3 //! //! //! //! Links //! ----- //! //! - Rust 1.9 //! + [blog post][1.9-blog] //! + [release notes] //! - [LLVM] //! + [Projects built with LLVM][LLVM projects] //! + [Wikipedia discussion] //! - MIR //! + [blog post][mir-blog] //! + [play.rust-lang.org] -- note the MIR button! //! + Two enhancements enabled by MIR: //! * Non-zeroing dynamic drop //! - [RFC][rfc-320] //! - [pull request and discussion][rfc-320-pr] //! * [Issue 811: "Non-lexical borrow scopes and better treatment of //! nested method calls"][issue-811] //! - [Cargo blog post] //! - `rustup` //! + [blog post][rustup-blog] //! + [install from rustup.rs][rustup.rs] //! //! [1.9-blog]: http://blog.rust-lang.org/2016/05/26/Rust-1.9.html //! [release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-190-2016-05-26 //! [LLVM]: http://llvm.org //! [LLVM projects]: http://llvm.org/ProjectsWithLLVM/ //! [Wikipedia discussion]: https://en.wikipedia.org/wiki/LLVM //! [mir-blog]: http://blog.rust-lang.org/2016/04/19/MIR.html //! [rfc-320]: https://github.com/rust-lang/rfcs/blob/master/text/0320-nonzeroing-dynamic-drop.md //! [rfc-320-pr]: https://github.com/rust-lang/rfcs/pull/320 //! [issue-811]: https://github.com/rust-lang/rfcs/issues/811 //! [Cargo blog post]: http://blog.rust-lang.org/2016/05/05/cargo-pillars.html //! [play.rust-lang.org]: https://play.rust-lang.org //! [rustup-blog]: http://blog.rust-lang.org/2016/05/13/rustup.html //! [rustup.rs]: https://www.rustup.rs //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - [Chris Palmer] //! - [Daniel Collin] //! - [Derek Morr] //! - Hamza Sheikh //! - Lachlan Collins //! - Leif Arne Storset //! - Luca Schmid //! - Micael Bergeron //! - [Pascal Hertleif] //! - Ralph Giles ("rillian") //! - Ralph "FriarTech" Loizzo //! - reddraggone9 //! - Ryan Ollos //! - Vesa Kaihlavirta //! - [William Roe] //! //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/news/_2.rs ================================================ //! Let's talk roadmap! //! //! - **Date:** December 29, 2016 //! - **Subject:** Rust's achievements in 2016 and goals for 2017 //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/2.mp3 //! //! //! //! Links //! ----- //! //! - Rust releases: //! + 1.10: [blog post][1.10-blog] | [release notes][1.10-rn] //! + 1.11: [blog post][1.11-blog] | [release notes][1.11-rn] //! + 1.12: [blog post][1.12-blog] | [release notes][1.12-rn] //! + 1.12.1: [blog post][1.12.1-blog] //! + 1.13: [blog post][1.13-blog] | [release notes][1.13-rn] //! + 1.14: [blog post][1.14-blog] | [release notes][1.14-rn] //! - Rust 2017 roadmap //! + [RFC text] //! + [RFC discussion] //! - Other official Rust blog posts: //! + [Shape of errors to come] //! + [Incremental compilation] //! * Milestone: [beta] //! * Milestone: [across crates] //! * Milestone: [in typechecking] //! - Cargo workspaces: //! + [Original RFC] and [discussion] //! + [Documentation] //! - Rust Language Service: //! + [Announcement post] on internals.rust-lang.org //! + [Demo] //! - Non-core projects mentioned on the show: //! + [Futures] //! + [Tokio] //! + [Rocket] //! - My projects //! + [Lightning] //! + RFC #1636: //! * [text][1636-text] //! * [discussion][1636-discussion] //! * [tracking issue][1636-tracking] (where you can contribute!) //! //! [1.10-blog]: https://blog.rust-lang.org/2016/07/07/Rust-1.10.html //! [1.10-rn]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1100-2016-07-07 //! [1.11-blog]: https://blog.rust-lang.org/2016/08/18/Rust-1.11.html //! [1.11-rn]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1110-2016-08-18 //! [1.12-blog]: https://blog.rust-lang.org/2016/09/29/Rust-1.12.html //! [1.12-rn]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1120-2016-09-29 //! [1.12.1-blog]: https://blog.rust-lang.org/2016/10/20/Rust-1.12.1.html //! [1.13-blog]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html //! [1.13-rn]: https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1130-2016-11-10 //! [1.14-blog]: https://blog.rust-lang.org/2016/12/22/Rust-1.14.html //! [1.14-rn]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1140-2016-12-22 //! [RFC text]: https://github.com/aturon/rfcs/blob/4f40ba07f2a0730c188cb5db6b0b9c5887ae1801/text/0000-roadmap-2017.md //! [RFC discussion]: https://github.com/rust-lang/rfcs/pull/1774 //! [Shape of errors to come]: https://blog.rust-lang.org/2016/08/10/Shape-of-errors-to-come.html //! [Incremental compilation]: https://blog.rust-lang.org/2016/09/08/incremental.html //! [beta]: https://github.com/rust-lang/rust/milestone/30 //! [across crates]: https://github.com/rust-lang/rust/milestone/31 //! [in typechecking]: https://github.com/rust-lang/rust/milestone/32 //! [Original RFC]: https://github.com/rust-lang/rfcs/blob/master/text/1525-cargo-workspace.md //! [discussion]: https://github.com/rust-lang/rfcs/pull/1525 //! [Documentation]: http://doc.crates.io/manifest.html#the-workspace-section //! [Announcement post]: https://internals.rust-lang.org/t/introducing-rust-language-server-source-release/4209 //! [Demo]: https://www.youtube.com/watch?time_continue=2405&v=pTQxHIzGqFI //! [Futures]: https://github.com/alexcrichton/futures-rs //! [Tokio]: https://github.com/tokio-rs/tokio //! [Rocket]: https://rocket.rs //! [Lightning]: https://github.com/chriskrycho/lightning-rs //! [1636-text]: https://github.com/rust-lang/rfcs/blob/master/text/1636-document_all_features.md //! [1636-discussion]: https://github.com/rust-lang/rfcs/pull/1636 //! [1636-tracking]: https://github.com/rust-lang/rust/issues/38643 //! //! //! Sponsors //! -------- //! //! - Aleksey Pirogov //! - Andreas Fischer //! - Ben Whitley //! - Cameron Mochrie //! - [Chris Palmer] //! - [Daniel Collin] //! - [Derek Morr] //! - [Jakub "Limeth" Hlusička] //! - [Jupp Müller] //! - Keith Gray //! - Lachlan Collins //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Raph Levien //! - reddraggone9 //! - Ryan Ollos //! - Steven Murawski //! - Vesa Kaihlavirta //! - Vlad Bezden //! - [William Roe] //! - Zaki //! //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Philipp Keller]: https://twitter.com/hansapla //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/news/_3.rs ================================================ //! Increasing Rust's Reach //! //! - **Date:** July 3, 2017 //! - **Subject:** Growing Rust's diversity to help Rust grow. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/3.mp3 //! //! //! //! //! Links and Notes //! --------------- //! //! - [Initiative blog post] //! - [Initiative submission form] //! //! [Initiative blog post]: https://blog.rust-lang.org/2017/06/27/Increasing-Rusts-Reach.html //! [Initiative submission form]: https://docs.google.com/forms/d/e/1FAIpQLSfbSGuoyZE9dctdEoC_XEZ7j2ox7jQT1zghAOF4iGds2PfBCA/viewform //! //! //! Sponsors //! -------- //! //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Christopher Giffard] //! - Dan Abrams //! - [Daniel Collin] //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jonathan Turner //! - Jordan Henderson //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - Sebastián Ramírez Magrí //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Warren Harper //! - [William Roe] //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Christopher Giffard]: http://blog.cgiffard.com //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) ================================================ FILE: src/news/mod.rs ================================================ //! News: occasional episodes dedicated to changes in Rust and its ecosystem. pub mod _1; pub mod _2; pub mod _3; // And now a slight change in when I publish. pub mod rust_1_20; pub mod rust_1_21_1_22; pub mod rust_1_23; pub mod rust_1_24; pub mod rust_1_25; pub mod rust_1_26; pub mod rust_1_27; pub mod rust_1_28; pub mod rust_1_29_1_30; pub mod rust_1_31; pub mod rust_1_32; pub mod rust_1_33_1_34; pub mod rust_1_35; ================================================ FILE: src/news/rust_1_20.rs ================================================ //! Rust 1.20 //! //! - **Date:** August 31, 2017 //! - **Subject:** Associated constants, conference season, meetups, and more! //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_20.mp3 //! //! //! //! //! Links and Notes //! --------------- //! //! - Rust 1.20 //! + [blog post] //! + [changelog] //! + [Associated items RFC] – and see the code for today's show for //! examples of the variants I described on the show! //! - [RustConf 2017] //! - [RustFest 2017] //! + [registration][rf-reg] //! - [Rust Belt Rust 2017] //! + [registration][rbr-reg] (and don't forget to use code `newrustacean` for 20% off!) //! - [rustrations.club] //! //! [blog post]: https://blog.rust-lang.org/2017/08/31/Rust-1.20.html //! [changelog]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1200-2017-08-31 //! [Associated items RFC]: https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md //! [RustConf 2017]: http://rustconf.com //! [RustFest 2017]: http://zurich.rustfest.eu //! [rf-reg]: https://ti.to/asquera-event-ug/rustfest-zurich/ //! [Rust Belt Rust 2017]: http://www.rust-belt-rust.com //! [rbr-reg]: https://www.eventbrite.com/e/rust-belt-rust-conference-2017-registration-36237335847 //! [rustrations.club]: http://rustrations.club //! //! Sponsors //! -------- //! //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - Dan Abrams //! - [Daniel Collin] //! - [David W. Allen] //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jonathan Turner //! - Jordan Henderson //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Piziak //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Philipp Keller //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Sebastián Ramírez Magrí] //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Warren Harper //! - [William Roe] //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: https://twitter.com/daniel_collin //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) trait Foo { const FOO: u32 = 0; } struct _Bar {} impl _Bar { const _BAR: u32 = 50; } impl Foo for _Bar {} enum _Baz {} impl _Baz { const _BAZ: u32 = 100; } impl Foo for _Baz {} #[cfg(test)] mod tests { use super::*; #[test] fn it_works() { // assert_eq!(Foo::FOO, 0); assert_eq!(_Bar::_BAR, 50); assert_eq!(_Bar::FOO, 0); assert_eq!(_Baz::_BAZ, 100); assert_eq!(_Baz::FOO, 0); } } ================================================ FILE: src/news/rust_1_21_1_22.rs ================================================ //! Rust 1.21 and 1.22 //! //! - **Date:** November 24, 2017 //! - **Subject:** Quality of life improvements, `Failure`, wasm, and rustdoc fun. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_21_1_22.mp3 //! //! //! //! //! Links and Notes //! --------------- //! //! - Rust 1.21 //! + [blog post][1.21] //! + ["When Will the RLS be Released?"][rls] //! - [Rust 1.22][1.22] //! - [Rusty Spike] //! - [Rust Fest] //! - [Rust Belt Rust] //! + [YouTube channel] //! + my talk: [script] and [slides] //! - [the `Failure` crate] //! + prior art: [error-chain] //! - [wasm support in Rust itself][wasm] //! - external Markdown files for docs //! + [the RFC] //! + [the implementation] //! //! [1.21]: https://blog.rust-lang.org/2017/10/12/Rust-1.21.html //! [rls]: https://www.ncameron.org/blog/when-will-the-rls-be-released/ //! [1.22]: https://blog.rust-lang.org/2017/11/22/Rust-1.22.html //! [Rusty Spike]: https://rusty-spike.blubrry.net //! [Rust Fest]: http://www.rustfest.eu //! [Rust Belt Rust]: http://rust-belt-rust.com //! [YouTube Channel]: https://www.youtube.com/channel/UCptxtVyJkQAJZcFwBbIDZcg //! [script]: http://www.chriskrycho.com/2017/becoming-a-contributor.html //! [slides]: http://www.chriskrycho.com/talks/rust-belt-rust/ //! [the `Failure` crate]: https://github.com/withoutboats/failure //! [error-chain]: https://github.com/rust-lang-nursery/error-chain //! [wasm]: https://github.com/rust-lang/rust/pull/45905 //! [the RFC]: https://github.com/rust-lang/rfcs/pull/1990 //! [the implementation]: https://github.com/rust-lang/rust/pull/44781 //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Anton Van Moere //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Caryn Finkelman //! - [Charlie Egan] //! - Chris Jones //! - Christian Schwarz //! - [Chris Palmer] //! - Dan Abrams //! - [Daniel Collin] //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - John Chandler //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Bettcher //! - Matthew Brenner //! - Matthew Piziak //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - Peter Tillemans //! - Peter Zuidhoek //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - Sam Whited //! - [Sebastián Ramírez Magrí] //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - [William Roe] //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Daniel Collin]: https://twitter.com/daniel_collin //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/news/rust-1-21-1-22.md")] pub struct Script; ================================================ FILE: src/news/rust_1_23.rs ================================================ //! Rust 1.23 //! //! - **Date:** January 5, 2018 //! - **Subject:** Rustdoc changes, the first `impl` period, Firefox Quantum, and more wasm! //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_23.mp3 //! //! //! //! //! ## Show notes //! //! - Rust 1.23 //! * [1.23 release notes] //! * [rustdoc tracking issue] //! * [rustdoc blog post] //! * [not copying function arguments] //! * [the first news episode] //! - the `impl` period //! * [`impl` period announcement] //! * [final newsletter] //! * [Diesel ORM] //! - [Firefox Quantum] //! * ["Fearless Concurrency in Firefox Quantum"] //! * [e015: Not dumb pointers.] //! - WebAssembly //! * [classic asteroids game] //! * [a password generator] //! * [Yew] //! * [JSX] //! * [stdweb] //! * [Glimmer VM spike] //! * ["Rust and the Case for WebAssembly in 2018"] //! - ["New Year’s Rust: A Call for Community Blogposts"] //! - [my other podcast, Winning Slowly] //! //! [1.23 release notes]: https://github.com/rust-lang/rust/blob/50989cd98dbef60b0b6f5baa0ce4203ce778adaa/RELEASES.md#version-1230-2018-01-04 //! [rustdoc tracking issue]: https://github.com/rust-lang/rust/issues/44229 //! [rustdoc blog post]: https://blog.guillaume-gomez.fr/articles/2017-09-18+New+rustdoc+rendering+common+errors //! [not copying function arguments]: https://github.com/rust-lang/rust/pull/45380 //! [the first news episode]: https://www.newrustacean.com/show_notes/news/_1/index.html //! [`impl` period announcement]: https://blog.rust-lang.org/2017/09/18/impl-future-for-rust.html //! [final newsletter]: https://internals.rust-lang.org/t/the-final-impl-period-newsletter/6408 //! [diesel orm]: http://diesel.rs/ //! [firefox quantum]: https://www.mozilla.org/en-US/firefox/quantum/ //! ["fearless concurrency in firefox quantum"]: https://blog.rust-lang.org/2017/11/14/Fearless-Concurrency-In-Firefox-Quantum.html //! [e015: not dumb pointers.]: https://www.newrustacean.com/show_notes/e015/index.html "Not dumb pointers" //! [classic asteroids game]: https://aochagavia.github.io/blog/rocket---a-rust-game-running-on-wasm/ //! [a password generator]: https://arkada38.github.io/2017/12/22/a-rust-password-generator-on-wasm/ //! [Yew]: https://github.com/DenisKolodin/yew //! [JSX]: https://reactjs.org/docs/introducing-jsx.html //! [stdweb]: https://github.com/koute/stdweb //! [Glimmer VM spike]: https://github.com/glimmerjs/glimmer-vm/pull/752 //! ["rust and the case for webassembly in 2018"]: https://mgattozzi.com/rust-wasm //! ["new year’s rust: a call for community blogposts"]: https://blog.rust-lang.org/2018/01/03/new-years-rust-a-call-for-community-blogposts.html //! [my other podcast, winning slowly]: http://www.winningslowly.org "Winning Slowly" //! //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - Daniel P. Clark //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/news/rust-1-23.md")] pub struct Script; ================================================ FILE: src/news/rust_1_24.rs ================================================ //! Rust 1.24 //! //! - **Date:** March 1, 2018 //! - **Subject:** Performance wins, incremental compilation, and the Rust 2018 Roadmap and Epoch. //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_24.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! - [Rust 1.24.0 blog post][1.24.0] //! - [Rust 1.24.1 blog post][1.24.1] //! - [Rust 2018 Roadmap RFC][2018 RFC] //! - [Rust Epochs RFC][epochs RFC] //! //! [1.24.0]: https://blog.rust-lang.org/2018/02/15/Rust-1.24.html //! [1.24.1]: https://blog.rust-lang.org/2018/03/01/Rust-1.24.1.html //! [2018 RFC]: https://github.com/rust-lang/rfcs/pull/2314 //! [epochs RFC]: https://github.com/rust-lang/rfcs/pull/2052 //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - [Derek Morr] //! - Eugene Bulkin //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Luca Schmid //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/news/rust-1-24.md")] pub struct Script; ================================================ FILE: src/news/rust_1_25.rs ================================================ //! Rust 1.25 //! //! - **Date:** March 31, 2018 //! - **Subject:** Paths and matches and SIMD, cargo new changes, and tons of //! community-driven learning materials! //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_25.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! - [Rust 1.25.0 blog post][1.25.0] //! - [RFC #1358] – `#[repr(align)]` //! - [RFC #2325] – SIMD stabilization //! - [RustConf CFP] //! - [Hello Rust] //! - [“Functional and Concurrent Programming in Rust”][book] //! //! [1.25.0]: https://blog.rust-lang.org/2018/03/29/Rust-1.25.html //! [RFC #1358]: https://github.com/rust-lang/rfcs/pull/1358 //! [RFC #2325]: https://github.com/rust-lang/rfcs/pull/2325 //! [RustConf CFP]: https://cfp.rustconf.com //! [Hello Rust]: https://hello-rust.show //! [book]: https://www.casadocodigo.com.br/pages/sumario-rust-funcional-concorrente //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Antonin Carette //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Brian Casiello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - Derek Buckley //! - [Derek Morr] //! - Eugene Bulkin //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Laurie Hedge //! - Luca Schmid //! - [Luiz Irber] //! - Mark LeMoine //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Raj Venkalil //! - [Ramon Buckley] //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Timm Preetz //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Luiz Irber]: http://luizirber.org/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckley]: http://www.inosion.com //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[allow(unused_imports)] use std::{ fs::{File, FileType}, path::Path, }; /// An example of the new match style. pub fn demo_match(s: &str) { match s { "some really long string so that rustfmt does not split this up" | "some other really long string, for the same reason" | "yet another string" => 10, "and of course we can wrap even more stuff the same way" | "and because the match arms don't have any differentiation" | "this actually is *unhelpful* in my view..." | "but you can use it if you want" => 20, _ => 0, }; } #[doc = include_str!("../../docs/news/rust-1-25.md")] pub struct Script; ================================================ FILE: src/news/rust_1_26.rs ================================================ //! Rust 1.26 //! //! - **Date:** May 14, 2018 //! - **Subject:** `impl trait`, `match` on references, `Result`s from `main`, //! and more. A good way to mark three years since Rust 1.0! //! - [**Audio**][mp3] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_26.mp3 //! //! //! //! //! Show Notes //! ---------- //! //! - Rust 1.26: //! - [blog post] //! - [release notes] //! - [RFC #2115] //! - [The Rusty Spike] //! - [webassembly.studio] //! - burntsushi's now-1.0 crates: //! - [regex] //! - [csv] //! - [docopt] //! - [Search crates VS Code plugin][vsc] //! //! [blog post]: https://blog.rust-lang.org/2018/05/10/Rust-1.26.html //! [release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1260-2018-05-10 //! [RFC #2115]: https://github.com/rust-lang/rfcs/blob/master/text/2115-argument-lifetimes.md //! [The Rusty Spike]: https://rusty-spike.blubrry.net/ //! [webassembly.studio]: https://webassembly.studio/ //! [regex]: https://crates.io/crates/regex //! [csv]: https://crates.io/crates/csv //! [docopt]: https://crates.io/crates/docopt //! [vsc]: https://marketplace.visualstudio.com/items?itemName=belfz.search-crates-io //! //! Sponsors //! -------- //! //! - Aaron Turon //! - adsertoris //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Antonin Carette //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Brandon "Spanky" Mills //! - Brian Casiello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - Dan Abrams //! - [Daniel Collin] //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - Derek Buckley //! - [Derek Morr] //! - Eugene Bulkin //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jonathan Turner //! - Joseph Hain //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Laurie Hedge //! - Luca Schmid //! - [Luiz Irber] //! - Mark LeMoine //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Raj Venkalil //! - [Ramon Buckley] //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - [Ryan Blecher] //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Timm Preetz //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Luiz Irber]: http://luizirber.org/ //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckley]: http://www.inosion.com //! [Ryan Blecher]: http://notryanb.github.io/ //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/news/rust-1-26.md")] pub struct Script; ================================================ FILE: src/news/rust_1_27.rs ================================================ //! Rust 1.27 //! //! - **Date:** June 30, 2018 //! - **Subject:** Stable SIMD, `dyn trait`, `rustfix` and the alpha release //! of the Rust 2018 Edition Preview! //! - [**Audio**][mp3] //! - [**Script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_27.mp3 //! [script]: https://newrustacean.com/show_notes/news/rust_1_27/struct.script //! //! //! //! //! Show Notes //! ---------- //! //! - Rust 1.27: //! - [blog post] //! - [release notes] //! - [This Week in Rust] //! - [The Rusty Spike] //! - [Hello Rust] //! //! [blog post]: https://blog.rust-lang.org/2018/06/21/Rust-1.27.html //! [release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1270-2018-06-21 //! [This Week in Rust]: https://this-week-in-rust.org //! [The Rusty Spike]: https://rusty-spike.blubrry.net/ //! [Hello Rust]: https://m.youtube.com/channel/UCZ_EWaQZCZuGGfnuqUoHujw //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Antonin Carette //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Brian Casiello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - [Damien Stanton] //! - Dan Abrams //! - [Daniel Collin] //! - [Daniel Mason] //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - Derek Buckley //! - [Derek Morr] //! - Eugene Bulkin //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - [John Rudnick] //! - Jon //! - Jonathan Turner //! - Joseph Hain //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Laurie Hedge //! - Luca Schmid //! - [Luiz Irber] //! - Mark LeMoine //! - [Martin Heuschober]: //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Coish] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Raj Venkalil //! - [Ramon Buckley] //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Sascha Grunert //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - Simon G. //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Timm Preetz //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Luiz Irber]: http://luizirber.org/ //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckley]: http://www.inosion.com //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/news/rust-1-27.md")] pub struct Script; ================================================ FILE: src/news/rust_1_28.rs ================================================ //! Rust 1.28 //! //! - **Date:** August 16, 2018 //! - **Subject:** Stable `#[global_allocator]`, more Rust 2018 Edition //! schedule news, video learning resources, and a static site generator! //! - [**Audio**][mp3] //! - [**Script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_28.mp3 //! [script]: https://newrustacean.com/show_notes/news/rust_1_28/struct.script //! //! //! //! //! Show Notes //! ---------- //! //! - Rust 1.28: //! - [blog post] //! - [release notes] //! - `wee_alloc`: //! - [repository] //! - [blog post][wee bp] //! - [rustfmt RC] //! - Community //! - [Nick Cameron’s LinuxConfAu 2018 tutorial] //! - [Gutenberg] //! //! [blog post]: https://blog.rust-lang.org/2018/08/02/Rust-1.28.html //! [release notes]: https://github.com/rust-lang/rust/blob/1.28.0/RELEASES.md //! [repository]: https://github.com/rustwasm/wee_alloc //! [wee bp]: http://fitzgeraldnick.com/2018/02/09/wee-alloc.html //! [rustfmt RC]: https://www.ncameron.org/blog/rustfmt-1-rc/ //! [Nick Cameron’s LinuxConfAu 2018 tutorial]: https://www.youtube.com/watch?v=vqavdUGKeb4 //! [Gutenberg]: https://getgutenberg.io //! //! Sponsors //! -------- //! //! - Aaron Turon //! - Alexander Payne //! - [Anthony Deschamps] //! - Anthony Scotti //! - Antonin Carette //! - Aleksey Pirogov //! - Andreas Fischer //! - Andrew Thompson //! - Austin LeSure //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brent Vatne //! - Brian Casiello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chris Jones //! - [Chris Palmer] //! - [Coleman McFarland] //! - [Damien Stanton] //! - Dan Abrams //! - [Daniel Collin] //! - [Daniel Mason] //! - [Daniel P. Clark] //! - [David W. Allen] //! - David Hewson //! - Derek Buckley //! - [Derek Morr] //! - Eugene Bulkin //! - [Hans Fjällemark] //! - [Henri Sivonen] //! - [Ian Jones] //! - [Jakub "Limeth" Hlusička] //! - James Cooper //! - Jerome Froelich //! - Joar Wandborg //! - [John Rudnick] //! - Jon //! - Jonathan Turner //! - Joseph Hain //! - [Jupp Müller] //! - Justin Ossevoort //! - [Karl Hobley] //! - Keith Gray //! - Kilian Rault //! - Laurie Hedge //! - Luca Schmid //! - [Luiz Irber] //! - Mark LeMoine //! - [Martin Heuschober]: //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - [Messense Lv] //! - Micael Bergeron //! - [Nathan Sculli] //! - [Nick Coish] //! - [Nick Stevens] //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal Hertleif] //! - [Patrick O'Doherty] //! - [Paul Naranja] //! - Peter Tillemans //! - Ralph Giles ("rillian") //! - Raj Venkalil //! - [Ramon Buckley] //! - Randy MacLeod //! - Raph Levien //! - reddraggone9 //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Sascha Grunert //! - [Sebastián Ramírez Magrí] //! - Shane Utt //! - [Simon Dickson] //! - Simon G. //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Timm Preetz //! - Tom Prince //! - Ty Overby //! - Tyler Harper //! - Vesa Kaihlavirta //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Yaacov Finkelman //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Brent Vatne]: https://github.com/brentvatne //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Coleman McFarland]: http://github.com/anxiousmodernman //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Fjällemark]: https://fjallemark.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Jakub "Limeth" Hlusička]: https://github.com/Limeth //! [John Rudnick]: http://www.cindur.com/ //! [Jupp Müller]: https://de.linkedin.com/in/juppm //! [Karl Hobley]: https://github.com/kaedroho/ //! [Luiz Irber]: http://luizirber.org/ //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal Hertleif]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckley]: http://www.inosion.com //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/news/rust-1-28.md")] pub struct Script; ================================================ FILE: src/news/rust_1_29_1_30.rs ================================================ //! Rust 1.29 and 1.30 //! //! - **Date:** November 17, 2018 //! - **Subject:** Procedural macros, better paths, and the Rust 2018 beta! //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_29_1_30.mp3 //! [script]: https://newrustacean.com/show_notes/news/rust_1_29_1_30/struct.script //! //! //! //! Show Notes //! ---------- //! //! Rust 1.29: //! //! - [blog post][1.29-blog] //! - [release notes][1.29-release] //! //! [1.29-blog]: https://blog.rust-lang.org/2018/09/13/Rust-1.29.html //! [1.29-release]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1290-2018-09-13 //! //! Rust 1.30: //! //! - [blog post][1.30-blog] //! - [release notes][1.30-release] //! - [RFC: path clarity][rfc] //! //! [1.30-blog]: https://blog.rust-lang.org/2018/10/25/Rust-1.30.0.html //! [1.30-release]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1300-2018-10-25 //! [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2126-path-clarity.md //! //! Sponsors //! -------- //! //! Thanks to Parity for sponsoring the show again. Go check out their [***Rust //! jobs***][parity]! //! //! [parity]: https://paritytech.io/jobs/ //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Payne //! - Alexander Kryvomaz //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Bryan Stitt] //! - Bryce Johnston //! - Caryn Finkelman //! - Cass Costello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Daniel //! - Dan Abrams //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Hewson //! - [Derek Morr] //! - Doug Reeves //! - Eugene Bulkin //! - Fábio Botelho //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - Jerome Froelich //! - [Joar Wandborg]: Joar Wandborg //! - [John Rudnick] //! - Jon //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Marhee //! - Justin Ossevoort //! - Kai Yao //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Tillemans //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Steffen Loen Sunde] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Zak van der Merwe //! - Zachary Snyder //! - Zaki //! //! [Anthony Deschamps]: https://github.com/adeschamps //! [Behnam Esfahbod]: https://github.com/behnam //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Joar Wandborg]: http://github.com/joar //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Steffen Loen Sunde]: https://www.ntnu.edu/employees/steffen.sunde //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/news/rust_1_29_1_30.md")] pub struct Script; ================================================ FILE: src/news/rust_1_31/mod.rs ================================================ //! A two-part special on Rust 1.31 and the 2018 Edition! pub mod part_1; pub mod part_2; ================================================ FILE: src/news/rust_1_31/part_1.rs ================================================ //! Rust 1.31 and the 2018 Edition, Part I //! //! - **Date:** January 7, 2019 //! - **Subject:** An overview of the edition, and some of the improvements that //! are available in both the 2015 and 2018 editions: better lifetime elision, //! some Cargo features, and some library stabilizations. //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_31/part_1.mp3 //! [script]: https://newrustacean.com/show_notes/news/rust_1_31/part_1/struct.script //! //! //! //! Show Notes //! ---------- //! //! - [Rust 1.31 Blog Post] //! - [Rust 1.31 Release Notes] //! - [Rust 2018 Edition Guide] //! - Previous episodes of direct interest: //! + [News: Rust 1.28] //! + [News: Rust 1.29 and 1.30] //! //! [Rust 1.31 Blog Post]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html //! [Rust 1.31 Release Notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1310-2018-12-06 //! [Rust 2018 Edition Guide]: https://rust-lang-nursery.github.io/edition-guide/rust-2018/index.html //! [News: Rust 1.28]: https://newrustacean.com/show_notes/news/rust_1_28/ "News: Rust 1.28" //! [News: Rust 1.29 and 1.30]: https://newrustacean.com/show_notes/news/rust_1_29_1_30/ "News: Rust 1.29 and 1.30" //! //! Sponsors //! -------- //! //! Thanks to Parity for sponsoring the show again. Go check out their [***Rust //! jobs***][parity]! //! //! [parity]: https://paritytech.io/jobs/ //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - [beaorn] //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Hewson //! - [Derek Morr] //! - Doug Reeves //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - [Fabio (decathorpe)] //! - Fábio Botelho //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - Jerome Froelich //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Marhee //! - Justin Ossevoort //! - Kai Yao //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - Michael Melanson //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Steffen Loen Sunde] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Zak van der Merwe //! - Zachary Snyder //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [beaorn]: https://github.com/beaorn //! [Behnam Esfahbod]: https://github.com/behnam //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Steffen Loen Sunde]: https://www.ntnu.edu/employees/steffen.sunde //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../../docs/news/rust-1-31/part-1.md")] pub struct Script; ================================================ FILE: src/news/rust_1_31/part_2.rs ================================================ //! Rust 1.31 and the 2018 Edition, Part II //! //! - **Date:** January 14, 2019 //! - **Subject:** Stabilizing rustfmt, clippy, tool lints, and `const fn` (all //! in both editions!), and the 2018 Edition-specific features: syntax //! changes and non-lexical lifetimes! //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_31/part_2.mp3 //! [script]: https://newrustacean.com/show_notes/news/rust_1_31/part_2/struct.script //! //! //! //! Show Notes //! ---------- //! //! - [Rust 1.31 Blog Post] //! - [Rust 1.31 Release Notes] //! - [Rust 2018 Edition Guide] //! - [a simple NLL example] //! - [`const fn` in the reference] and [“const contexts”] //! - [“uniform paths”] //! - [the raw string syntax] //! //! [Rust 1.31 Blog Post]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html //! [Rust 1.31 Release Notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1310-2018-12-06 //! [Rust 2018 Edition Guide]: https://rust-lang-nursery.github.io/edition-guide/rust-2018/index.html //! [a simple NLL example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f497716877668a5f0dc904e24ffc207a //! [`const fn` in the reference]: https://doc.rust-lang.org/reference/items/functions.html#const-functions //! [“uniform paths”]: https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html#uniform-paths //! [the raw string syntax]: https://doc.rust-lang.org/stable/reference/tokens.html#string-literals //! [“const contexts”]: https://doc.rust-lang.org/reference/const_eval.html#const-context //! //! Sponsors //! -------- //! //! Thanks to Parity for sponsoring the show again. Go check out their [***Rust //! jobs***][parity]! //! //! [parity]: https://paritytech.io/jobs/ //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - [beaorn] //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Hewson //! - [Derek Morr] //! - Doug Reeves //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - [Fabio (decathorpe)] //! - Fábio Botelho //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - Jerome Froelich //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Marhee //! - Justin Ossevoort //! - Kai Yao //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - Michael Melanson //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Steffen Loen Sunde] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Zak van der Merwe //! - Zachary Snyder //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [beaorn]: https://github.com/beaorn //! [Behnam Esfahbod]: https://github.com/behnam //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Steffen Loen Sunde]: https://www.ntnu.edu/employees/steffen.sunde //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../../docs/news/rust-1-31/part-2.md")] pub struct Script; ================================================ FILE: src/news/rust_1_32.rs ================================================ //! Rust 1.32 //! //! - **Date:** January 22, 2019 //! - **Subject:** `dbg!`, unified paths, more places you can use `Self`, and a //! *bunch* of `const fn` stabilizations—plus some neat community highlights! //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_32.mp3 //! [script]: https://newrustacean.com/show_notes/news/rust_1_32/struct.script //! //! //! //! Show Notes //! ---------- //! //! - Rust 1.32 //! - [blog post] //! - [release notes] //! - [smaller builds on Twitter][Twitter] //! - [Amethyst] //! - [examples] //! - [docs] //! - [RustConf 2018 keynote] //! - [insta] //! //! [blog post]: https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html //! [release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1320-2019-01-17 //! [Twitter]: https://twitter.com/softprops/status/1086723200095059972 //! [Amethyst]: https://www.amethyst.rs/ //! [examples]: https://github.com/amethyst/amethyst/tree/v0.10.0/examples //! [docs]: https://www.amethyst.rs/book/latest/ //! [RustConf 2018 keynote]: https://m.youtube.com/watch?v=aKLntZcp27M //! [insta]: https://crates.io/crates/insta //! //! Sponsors //! -------- //! //! Thanks to Parity for sponsoring the show again. Go check out their [***Rust //! jobs***][parity]! //! //! [parity]: https://paritytech.io/jobs/ //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - Arlen Haftevani //! - [beaorn] //! - [Behnam Esfahbod] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Cat Dad //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Hewson //! - [Derek Morr] //! - Doug Reeves //! - Douglas Correa //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - [Fabio (decathorpe)] //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - Hoàng Đức Hiếu //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - Jerome Froelich //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - Jonah //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - [Joe Percy] //! - Justin Ossevoort //! - Kai Yao //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - [Michael Melanson] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Steffen Loen Sunde] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Zak van der Merwe //! - Zachary Snyder //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [beaorn]: https://github.com/beaorn //! [Behnam Esfahbod]: https://github.com/behnam //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [Joe Percy]: http://joetdc.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Michael Melanson]: https://www.michaelmelanson.net //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Steffen Loen Sunde]: https://www.ntnu.edu/employees/steffen.sunde //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/news/rust-1-32.md")] pub struct Script; ================================================ FILE: src/news/rust_1_33_1_34.rs ================================================ //! Rust 1.33 and 1.34 //! //! - **Date:** April 19, 2019 //! - **Subject:** Moar `const fn`, some `Pin`, and alternative Cargo registries! //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_33_1_34.mp3 //! [script]: https://newrustacean.com/show_notes/news/rust_1_33_1_34/struct.script //! //! //! //! Show Notes //! ---------- //! //! - [1.33 release notes] //! - `Pin` //! - [RFC] //! - [API docs] //! - [1.34 release notes] //! //! [1.33 release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1330-2019-02-28 //! [1.34 release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1340-2019-04-11 //! [RFC]: https://github.com/rust-lang/rfcs/blob/master/text/2349-pin.md //! [API docs]: https://doc.rust-lang.org/std/pin/index.html //! //! Sponsors //! -------- //! //! Thanks to Parity for sponsoring the show and hiring Rust developers! //! //! [parity]: https://www.parity.io/jobs //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Lozada //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - Arlen Haftevani //! - [Arlo (Hyena)] //! - [Arun Kulshreshtha] //! - [Behnam Esfahbod] //! - [Benjamin Manns] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Cat Dad //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Christoffer Ceutz //! - Cristian Paul //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Carroll //! - David Hewson //! - [Derek Morr] //! - Dominic Cooney //! - Doug Reeves //! - [Douglas Correa] //! - Edmund Kump //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - [Evan Stoll] //! - [Fabio (decathorpe)] //! - [Fabio Correa] //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - Hoàng Đức Hiếu //! - [Hugo Josefson] //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - [Jason Bowen] //! - [Jeff May] //! - [Jendrik Illner] //! - Jerome Froelich //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - Jonah //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Mou //! - Joseph Schrag //! - [Joe Percy] //! - Justin Ossevoort //! - Kai Yao //! - Kazutaka Mise //! - Keith Gray //! - Kilian Rault //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Malnormalulo] //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - [Michael Melanson] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Oladapo Fadeyi //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - [Ryan Blecher] //! - [Ryan Osial] //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Soren Bramer Schmidt] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Tim Brooks //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - [William Roe] //! - Zak van der Merwe //! - Zachary Snyder //! - [Zach Peters] //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [Arlo (Hyena)]: https://asonix.dog/@asonix //! [Arun Kulshreshtha]: https://github.com/kulshrax //! [Behnam Esfahbod]: https://github.com/behnam //! [Benjamin Manns]: https://www.benmanns.com/ //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Douglas Correa]: http://learnrust.io/ //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Evan Stoll]: https://github.com/evanjs //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Fabio Correa]: https://linkedin.com/in/feamcor //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Hugo Josefson]: https://www.hugojosefson.com //! [Jason Bowen]: https://twitter.com/jwbowen //! [Jeff May]: https://gitlab.com/jeffmay //! [Jendrik Illner]: https://www.jendrikillner.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [Joe Percy]: http://joetdc.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Malnormalulo]: https://twitter.com/Malnormalulo //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Michael Melanson]: https://www.michaelmelanson.net //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Soren Bramer Schmidt]: http://prisma.io/ //! [Stuart Hinson]: http://stuarth.github.io/ //! [William Roe]: http://willroe.me //! [Zach Peters]: https://github.com/zpeters //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/news/rust-1.33-and-1.34.md")] pub struct Script; ================================================ FILE: src/news/rust_1_35.rs ================================================ //! Rust 1.35 //! //! - **Date:** May 23, 2019 //! - **Subject:** WASI, `Option::copied`, and the future of async/await syntax! //! - [**download mp3**][mp3] //! - [**script**][script] //! //! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/news/rust_1_35.mp3 //! [script]: https://newrustacean.com/show_notes/news/rust_1_35/struct.script //! //! //! //! Show Notes //! ---------- //! //! - Rust 1.34.1 //! - [release notes][1.34.1 release notes] //! - [blog post][1.34.1 blog post] //! - [discussion about `Error::type_id`] //! - Rust 1.34.2 //! - [release notes][1.34.2 release notes] //! - [blog post][1.34.2 blog post] //! - [discussion about `Error::type_id`] //! - Rust 1.35 //! - [release notes] //! - [blog post] //! - [WASI] //! - [The Bike Shed episode] //! - Async/await //! - [`std::futures` API docs] //! - [internal thread on syntax for `.await`] //! //! [1.34.1 release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1341-2019-04-25 //! [1.34.1 blog post]: https://blog.rust-lang.org/2019/04/25/Rust-1.34.1.html //! [1.34.2 release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1342-2019-05-14 //! [1.34.2 blog post]: https://blog.rust-lang.org/2019/05/14/Rust-1.34.2.html //! [discussion about `Error::type_id`]: https://github.com/rust-lang/rust/issues/60784 //! [release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1350-2019-05-23 //! [blog post]: https://blog.rust-lang.org/2019/05/23/Rust-1.35.0.html //! [WASI]: https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-intro.md //! [The Bike Shed episode]: http://bikeshed.fm/195 //! [`std::futures` API docs]: https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.16/futures/ //! [internal thread on syntax for `.await`]: https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021 //! //! Sponsors //! -------- //! //! Thanks to Parity for sponsoring the show and hiring Rust developers! //! //! [parity]: https://www.parity.io/jobs //! //! ### Patreon Sponsors //! //! - Adam Green //! - Aleksey Pirogov //! - Alexander Kryvomaz //! - Alexander Lozada //! - Alexander Payne //! - [Andrew Dirksen] //! - Andrew Thompson //! - [Anthony Deschamps] //! - Anthony Scotti //! - Arlen Haftevani //! - [Arlo (Hyena)] //! - Arun Kulshreshtha //! - [Behnam Esfahbod] //! - [Benjamin Manns] //! - Benjamin Wasty //! - Brandon 'Spanky' Mills //! - Brian Casiello //! - Brian Manning //! - [Brian McCallister] //! - [Bryan Stitt] //! - Caryn Finkelman //! - Cass Costello //! - Cat Dad //! - Chap Lovejoy //! - [Charlie Egan] //! - Chip //! - [Chris Palmer] //! - Christoffer Ceutz //! - Cristian Paul //! - Dan Abrams //! - Daniel //! - Daniel Bross //! - [Daniel Collin] //! - [Daniel Mason] //! - David Carroll //! - David Hewson //! - [Derek Morr] //! - Dominic Cooney //! - Doug Reeves //! - [Douglas Correa] //! - Edmund Kump //! - [Eduard Knyshov] //! - [Embark Studios] //! - Eugene Bulkin //! - [Evan Stoll] //! - [Fabio (decathorpe)] //! - [Fabio Correa] //! - Freeman P. Pascal //! - [Gaveen Prabhasara] //! - [Graham Wihlidal] //! - [Henri Sivonen] //! - [Ian Jones] //! - Hoàng Đức Hiếu //! - [Hugo Josefson] //! - "Jake ""ferris"" Taylor" //! - Jako Danar //! - James Cooper //! - James Hagans II //! - [Jason Bowen] //! - [Jeff May] //! - [Jendrik Illner] //! - Jerome Froelich //! - JockeTF //! - [Joar Wandborg] //! - [Johan Andersson] //! - [John Rudnick] //! - Jon //! - Jonah //! - [Jonathan Knapp] //! - Jonathan Turner //! - Joseph Hain //! - Joseph Mou //! - Joseph Schrag //! - [Joe Percy] //! - Justin Ossevoort //! - Kai Yao //! - Kazutaka Mise //! - Keith Gray //! - Kilian Rault //! - Kyle //! - Lee Jenkins //! - Luca Schmid //! - [Luiz Irber] //! - Lukas Eller //! - [Malnormalulo] //! - [Martin Heuschober] //! - Masashi Fujita //! - Matt Rudder //! - Matthew Brenner //! - Matthias Ruszala //! - [Max Jacobson] //! - Max R.R. Collada //! - [Messense Lv] //! - Micael Bergeron //! - [Michael Mc Donnell] //! - [Michael Melanson] //! - Michael Sanders //! - [Nathan Sculli] //! - [Nick Coish] //! - Nick Gideo //! - [Nick Stevens] //! - [Nicolas Pochet] //! - Oladapo Fadeyi //! - Olaf Leidinger //! - Oliver Uvman //! - [Oluseyi Sonaiya] //! - Ovidiu Curcan //! - [Pascal] //! - [Patrick O'Doherty] //! - Paul Naranja //! - Paul Osborne //! - Peter Scholtens //! - Peter Tillemans //! - Pierre-Antoine Champin //! - Ralph Giles //! - [Ramon Buckland] //! - Randy MacLeod //! - Raph Levien //! - Richard Dallaway //! - Rob Tsuk //! - [Robbie Clarken] //! - Robert Chrzanowski //! - Romain Chossart //! - [Ryan Blecher] //! - [Ryan Osial] //! - Satoshi Yoshikawa //! - Scott Moeller //! - [Sebastián Ramírez Magrí] //! - [Simon Dickson] //! - Simon G //! - [Soren Bramer Schmidt] //! - Steve Jenson //! - Steven Knight //! - Steven Murawski //! - [Stuart Hinson] //! - Sven Huster //! - Tim Brooks //! - Tim Small //! - Tim Süberkrüb //! - Tom Prince //! - Toolmaker's Guild //! - Ty Overby //! - Tyler Harper //! - Victor Kruger //! - Will Greenberg //! - Zak van der Merwe //! - Zachary Snyder //! - [Zach Peters] //! - Zaki //! //! [Andrew Dirksen]: https://github.com/bddap //! [Anthony Deschamps]: https://github.com/adeschamps //! [Arlo (Hyena)]: https://asonix.dog/@asonix //! [Behnam Esfahbod]: https://github.com/behnam //! [Benjamin Manns]: https://www.benmanns.com/ //! [Brian McCallister]: https://skife.org/ //! [Bryan Stitt]: http://www.stitthappens.com/ //! [Charlie Egan]: https://charlieegan3.com //! [Chris Palmer]: http://red-oxide.org/ //! [Damien Stanton]: https://github.com/damienstanton //! [Daniel Collin]: https://twitter.com/daniel_collin //! [Daniel Mason]: https://github.com/gisleburt //! [Daniel P. Clark]: https://6ftdan.com/ //! [David W. Allen]: http://GitHub.com/DataRiot //! [Derek Morr]: https://twitter.com/derekmorr //! [Douglas Correa]: http://learnrust.io/ //! [Eduard Knyshov]: https://github.com/edvorg //! [Embark Studios]: https://www.embark-studios.com //! [Evan Stoll]: https://github.com/evanjs //! [Gaveen Prabhasara]: https://twitter.com/gaveen //! [Fabio (decathorpe)]: https://decathorpe.com/ //! [Fabio Correa]: https://linkedin.com/in/feamcor //! [Graham Wihlidal]: https://wihlidal.com/ //! [Henri Sivonen]: https://hsivonen.fi/ //! [Ian Jones]: https://www.ianmjones.com/ //! [Hugo Josefson]: https://www.hugojosefson.com //! [Jason Bowen]: https://twitter.com/jwbowen //! [Jeff May]: https://gitlab.com/jeffmay //! [Jendrik Illner]: https://www.jendrikillner.com/ //! [Joar Wandborg]: http://github.com/joar //! [Johan Andersson]: https://www.embark-studios.com //! [Jonathan Knapp]: https://www.coffeeandcode.com/ //! [Joe Percy]: http://joetdc.com/ //! [John Rudnick]: http://www.cindur.com/ //! [Luiz Irber]: http://luizirber.org/ //! [Malnormalulo]: https://twitter.com/Malnormalulo //! [Martin Heuschober]: https://github.com/epsilonhalbe //! [Max Jacobson]: https://twitter.com/maxjacobson //! [Messense Lv]: https://github.com/messense //! [Michael Mc Donnell]: https://www.linkedin.com/in/michaelmcdonnell/ //! [Michael Melanson]: https://www.michaelmelanson.net //! [Nathan Sculli]: http://influential.co/ //! [Nick Coish]: http://github.com/ncoish //! [Nick Stevens]: https://github.com/nastevens //! [Nicolas Pochet]: https://github.com/n-pochet //! [Oluseyi Sonaiya]: http://oluseyi.info/ //! [Pascal]: https://pascalhertleif.de/ //! [Patrick O'Doherty]: https://twitter.com/patrickod //! [Philipp Keller]: https://twitter.com/hansapla //! [Ramon Buckland]: http://www.inosion.com //! [Robbie Clarken]: https://github.com/RobbieClarken/ //! [Ryan Blecher]: http://notryanb.github.io/ //! [Ryan Osial]: https://github.com/osialr //! [Sebastián Ramírez Magrí]: https://www.twitter.com/sebasmagri //! [Simon Dickson]: https://www.simonhdickson.com/ //! [Soren Bramer Schmidt]: http://prisma.io/ //! [Stuart Hinson]: http://stuarth.github.io/ //! [Zach Peters]: https://github.com/zpeters //! //! (Thanks to the couple people donating who opted out of the reward tier, as //! well. You know who you are!) //! //! ### Become a sponsor //! //! - Patreon //! - [Venmo](https://venmo.com/chriskrycho) //! - [Dwolla](https://www.dwolla.com/hub/chriskrycho) //! - [Cash.me](https://cash.me/$chriskrycho) //! - [Flattr](https://flattr.com/profile/chriskrycho) //! - [PayPal.me](https://paypal.me/chriskrycho) //! //! //! Contact //! ------- //! //! - New Rustacean: //! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean) //! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com) //! - Chris Krycho //! + GitHub: [chriskrycho](https://github.com/chriskrycho) //! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho) #[doc = include_str!("../../docs/news/rust-1.35.md")] pub struct Script;