Chris Krycho - Rusthttp://v4.chriskrycho.com/Mon, 15 Jul 2019 16:45:00 -0400Appearance: Corecursive #34http://v4.chriskrycho.com/2019/appearance-corecursive-34.html<p>I was delighted to spend a bit over an hour <a href="https://corecursive.com/034-chris-krycho-typescript/">chatting with Adam Gordon Bell on the Corecursive podcast</a>. I was there officially to talk about TypeScript, and I did a <em>lot</em> of that… but we also dug into Rust a bit, of course, as well as talking about my schedule and “productivity”.</p> <p>I’ve been podcasting for a few years now, but this was only the second time I’ve ever been on someone <em>else’s</em> podcast—and it was a blast. Thanks so much to Adam for having me on!</p> Chris KrychoMon, 15 Jul 2019 16:45:00 -0400tag:v4.chriskrycho.com,2019-07-15:/2019/appearance-corecursive-34.htmlTypeScriptpodcastingRustprogramming languagesappearancesJavaScript is Chttp://v4.chriskrycho.com/2018/javascript-is-c.html<p><i><b><a href="https://v4.chriskrycho.com/2018/assumed-audiences.html">Assumed Audience:</a></b> software developers, especially those interested in modern, typed programming languages.</i></p> <p>Earlier this week, I was working on a problem in the Ember app where I spend most of my day job, and realized: <i>JavaScript is the same as C.</i></p> <p>That probably doesn’t make any sense, so let’s back up. The scenario I was dealing with was one where there was a bit of invariant around a piece of data that I <em>had</em> to maintain for the application not to blow up in horrible ways, but had no good way to enforce with the language’s tools. <em>This</em> action on <em>that</em> piece of data was only valid if <em>this</em> condition held true… but even with the fully-type-checked TypeScript application we now have, the action (because of the entire application’s architecture and indeed the entire way that Ember apps are wired together!) could not be statically verified to be safe.</p> <p>As I considered the best way to handle this—I ended up having the function involved in the action just throw an error if the invariant wasn’t properly maintained—I was reminded of the years I spent writing C. In C, it’s quite <em>possible</em> to write safe code around memory management. I managed it fine in the applications I worked on, by carefully documenting the invariants a given function required to be safe. <em>This</em> piece of data is allocated by <em>that</em> function and then released to <em>the caller</em> to manage. Even with every bit of static analysis I threw at those kinds of things, it was possible to get it wrong.</p> <p>The exact same kinds of problems I had in C, I have in JavaScript or even TypeScript today. Experientially, JavaScript<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> <em>is</em> C, as far as having to deal with these kinds of invariants goes.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p> <p>Enter <a href="https://www.rust-lang.org">Rust</a>: the kinds of management of memory that I was always having to keep track of in my head (or, better, with detailed documentation comments along the way—but with the same problem that it was easy to get wrong), I could now have statically guaranteed by a compiler. Given that I spent the first six years of my career managing and carefully tracking all of that by hand, it’s no wonder I <a href="https://newrustacean.com">fell in love</a> with Rust. I could have the <em>compiler</em> guarantee the invariants I needed around memory management.</p> <p>And it turns out, this same dynamic exists in the world of front-end web development. People sometimes wonder why (and colleagues are often bemused that) I get so excited by <a href="https://elm-lang.org">Elm</a>. But the step from JavaScript (or even TypeScript) to Elm is just like the step from C to Rust. It’s a real and profound shift in what kinds of things you can <em>know for certain</em> about your program.</p> <p>In a C application, try as hard as I may, at the end of the day I am always on my own, making sure the invariants I need for memory safety hold. In Rust, I can be 100% confident that I will not have memory-unsafe code. Not 98%-and-I’d-better-check-those-last-2%-really-closely. One hundred percent. That’s a game-changer.</p> <p>In a JavaScript or TypeScript application, try as hard as I may, at the end of the day I am always on my own, making sure the invariants I need for state management hold. In Elm, I can be 100% confident that I will not have code which needs a given invariant about a piece of state to hold break the way it could in this TypeScript application. Because I can’t even apply the relevant transformations in question if it isn’t! That’s a game-changer.</p> <p>Neither of those is a guarantee I won’t have bugs. (A compiler that could guarantee that would have to be sentient and far smarter than any human!) Neither of them means I can’t intentionally do stupid things that violate invariants in ways that get the program into broken states from the user’s point of view. But both of them give me the tools and the confidence that I can absolutely guarantee that certain, very important kinds of invariants hold. We’re not looking for an absence of all bugs or a system which can prevent us from making any kind of mistake. We’re looking to be able to spend our times on the things that matter, <em>not</em> on minutiae the computer can check for us.</p> <p>So: I’m not going back to C, and I’m ready to move past JavaScript and TypeScript.</p> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>This goes for plenty of languages that aren’t JavaScript, too. It’s equally true of c<sup>♯</sup> or Python.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn2" role="doc-endnote"><p>Obviously there are some kinds of things you don’t have to worry about in JS that you do in C: memory management, for one. The point is that the manual-verification-of-every-invariant-you-care-about is the same.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoThu, 20 Dec 2018 18:45:00 -0500tag:v4.chriskrycho.com,2018-12-20:/2018/javascript-is-c.htmlJavaScriptTypeScriptElmRustCsoftware developmentReview: The Rust Programming Languagehttp://v4.chriskrycho.com/2018/review-the-rust-programming-language.html<p><i class=editorial>I intended to publish this review months ago, but the single hardest month of my career punched me in the face repeatedly and I just found myself entirely unable to write for all of September and most of October. Here it is at last, with apologies to No Starch for the delay!</i></p> <hr /> <p>No Starch Press kindly provided me with a review copy of <a href="https://nostarch.com/Rust"><cite>The Rust Programming Language</cite></a>, by Steve Klabnik and Carol Nichols, with contributions from the Rust community. A <em>real-world, physical</em> review copy. And it’s magnificent.</p> <figure> <img src="https://f001.backblazeb2.com/file/chriskrycho-com/images/trpl.jpg" alt="The Rust Programming Language" /><figcaption><cite>The Rust Programming Language</cite></figcaption> </figure> <p>I’ve read the vast majority of this book (as well as the previous edition) online over the last couple years as Steve and Carol have worked on it; it has been an invaluable resource for many a <a href="https://newrustacean.com">New Rustacean</a> episode. (Bonus: you can hear me talk with Carol about working on <cite>The Rust Programming Language</cite> in <a href="https://newrustacean.com/show_notes/interview/_3/index.html">my interview with her back in 2016</a>! And yes: writing the book took that long.) This is in some sense <em>the</em> authoritative book on Rust.</p> <p>You might wonder why you’d pick up a physical copy of this book given that it is available online for free. There are a few reasons that come to mind:</p> <ol type="1"> <li><p>The quality of the online book is in many ways a direct result of No Starch Press’ deep investment in the text. They’re not making any money from the online copy. They <em>do</em> recoup some of their costs when we buy ebook or physical copies. So that’s one good reason: a way of saying “thank you!” and investing in the continued existence of No Starch and projects like this.</p></li> <li><p>I used the word <em>magnificent</em> above to describe this, and I mean it. This printing is a fabulous example of really excellent book design. I take typography and presentation seriously, and not a whit less for programming books than for copies of <cite>The Lord of the Rings</cite>. Everything in this printing is top-notch. Little details like the way that code listings are displayed—right down to the way some text is faded away to emphasize what’s <em>new</em> in a listing—make this one of the most readable programming texts I’ve ever seen.</p></li> <li><p>As delightful and powerful as hypertext is, the physicality of a book is equally delightful and powerful, just in different ways. There is nothing quite like the tactile experience of flipping through a book. Nothing in digital text lets you forge connections to learning the way that scribbling notes in a margin does. And the sheer physicality of a volume this large gives you mental hooks to hang what you’re learning on: you can remember that it felt like <em>this</em> to have the book open to where you learned it.</p></li> </ol> <p>(That last point is an argument in favor of printed books in general. You can expect me to come back to that theme time and again in this space, even while I continue to value digital spaces like this one for what <em>they</em> uniquely do.)</p> <p>No Starch sent me this copy to review with no expectation of a positive review—but even if they’d been paying me, they couldn’t make me say that this book is <em>great</em>. But great it is. If you have any interest in <a href="https://www.rust-lang.org/en-US/">Rust</a>, you should grab a copy!</p> Chris KrychoWed, 07 Nov 2018 07:00:00 -0500tag:v4.chriskrycho.com,2018-11-07:/2018/review-the-rust-programming-language.htmlbook reviewsrustprogramming languagesScales of Feedback Time in Software Developmenthttp://v4.chriskrycho.com/2018/scales-of-feedback-time-in-software-development.html<p><i class=editorial><strong><a href="http://v4.chriskrycho.com/2018/assumed-audiences.html">Assumed Audience</a>:</strong> fans of compiled languages with expressive type systems. I’m not trying to persuade fans of dynamic languages they should use a compiler here; I’m trying to surface something that often goes unstated in discussions among fans of compiled languages with expressive type systems, but hopefully it’s interesting beyond that. If you don’t like compiled languages, just skip the build step bits; the rest all still applies.</i></p> <p>There are basically six stages of the development of any given software component where you can receive feedback on what you build:<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p> <ol type="1"> <li>compilers, static analysis tools, and/or pair programming</li> <li>automated test suites</li> <li>manual local testing</li> <li>continuous integration (<abbr>CI</abbr>) test results</li> <li>deploying to staging (or a similar test environment) for manual testing</li> <li>deploying to live, i.e. when production traffic is meaningfully different from what you can test on staging</li> </ol> <p>What’s interesting to note is that there are also, in my experience, roughly order-of-magnitude differences between each of those layers in terms of the <em>cycle time</em> between when you make a change and whether you know it is broken. That is, there seem to be rough factor-of-ten differences between the feedback you get from—</p> <ol type="1"> <li><p>compilers, static analysis tools, and/or pair programming—all of which can show you feedback in near-real-time as you’re typing and saving your code, especially with a good language server or a fast compiler or a speedy linter</p></li> <li><p>automated test suites, assuming they’re running on every build change and are reasonably speedy themselves, or scoped to the things impacted by the changes made</p></li> <li><p>manual local testing, which you can repeat after every build, but which usually requires you to switch contexts to execute the program in some way</p></li> <li><p><abbr>CI</abbr>, presumably doing the automated equivalent of what you do in both layers 2 and 3, but requiring a push to some central location and a remote build and execution of the test suite, and often a much larger integration test suite than you’d run locally</p></li> <li><p>deploying to staging, and repeating the same kinds of manual testing you might do locally in layer 2 in a more production-like environment</p></li> <li><p>deploying to live, and repeating the same kinds of manual testing you might do locally in layers 2 or 5, as well as getting feedback from observability or monitoring systems using your real traffic</p></li> </ol> <p>(Those last two <em>might</em> be comparable in the cycle time sense. However, the way most teams I’ve heard of work, any deploy to live is usually preceded by a deploy to staging. What’s more, with most changes that you can’t test until it’s live, it’s often the case that you’re not going to know if something is wrong until it has been live for at least a little while. Finally, some kinds of things you can really only test with production load and monitoring or observability systems, and those kinds of things are at least sometimes not to be visible immediately after deployment, but only in the system’s aggregate behavior or weird outliers that show up given enough scale.)</p> <p>What all of this gets at is that stepping to a higher layer nearly always entails a <em>dramatic</em> increase in the <em>cycle time</em> for software development: that is, the amount of time between when I make a change and when I know whether it’s broken or not. If I can know that I have a problem because my compiler surfaces errors in my editor, that probably saves me a minute or two each day over only being able to see the same error in a test suite. By the same token, being able to surface an error in a test suite running on every build will likely save me anything from minutes to hours of cycle time compared to something I can only test in production.</p> <p>At first blush, this looks like an argument for pushing everything to the lowest-numbered layer possible, and I think that’s <em>kind of</em> right. I (and probably many other people who end up in, say, Rust or Haskell or Elm or other languages with similarly rich type systems) tend to prefer putting as much as possible into layer 1 here precisely because we have so often been bitten by things that are at layer 2 in other languages or frameworks and take a lot of time to figure out why they broke at layer 2. This happened to me in a C<sup>♯</sup> server application just a couple weeks ago, and chasing it down was <em>not fun</em>.</p> <p>However, my enthusiasm for rich type systems notwithstanding, I <em>don’t</em> think this observation about these layers of cycle time means we should put everything in the compiler all the time. Indeed, there are some things it is too expensive or difficult to test anywhere <em>but</em> production (all the way up at layer 6). What’s more–although this is often overlooked in these discussions–putting too much of this rich information in layer 1 can absolutely kill your compile times in many languages. In my experience, this is particularly true of many of the languages with rich enough type systems to make layer 1 handling genuinely viable in the first place!<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p> <p>I do think, though, that being aware of the cost in cycle time is useful, as is being explicit about <em>why</em> we think it’s worth slotting a particular set of feedback into layer 2 vs. layer 1 (or layers 3, 4, 5, or 6). That goes for library development, of course.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> It goes equally for application development, though! It can be really helpful to make explicit both which of these layers you’re landing in and (just as important) why you’ve landed there for any given bit of feedback you want or need to get–making the tradeoffs explicit along the way.</p> <hr /> <p><i class=editorial>Thanks to my friend Ben Makuh for looking over an earlier draft of this piece and providing really helpful feedback on it! Thanks as well to Greg Vaughn for noting shortly after I published it that pair programming also sits at the “immediate feedback” layer.</i></p> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>There’s some ongoing work in the Rust web working group to build an exemplar web framework, <a href="https://rust-lang-nursery.github.io/wg-net/2018/09/11/tide.html">Tide</a>. The <a href="https://rust-lang-nursery.github.io/wg-net/2018/10/16/tide-routing.html">most recent post</a> tackled routing, and prompted <a href="https://internals.rust-lang.org/t/routing-and-extraction-in-tide-a-first-sketch/8587">an interesting discussion</a> on the <a href="https://internals.rust-lang.org/">Rust internals forum</a>. This post is a cleaned-up, better-articulated, more general version of <a href="https://internals.rust-lang.org/t/routing-and-extraction-in-tide-a-first-sketch/8587/36?u=chriskrycho">a post</a> I offered in that thread.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn2" role="doc-endnote"><p>Right now I and a few others are trying to figure out why one particular type definition in the TypeScript definitions for Ember.js causes a build to take about 20× as long as the build without that type definition. It’s the difference between a 6.5-second build and a 2.5-<em>minute</em> build.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn3" role="doc-endnote"><p>as in the example of a web server’s <abbr>API</abbr> for route handling which originally prompted this post<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoMon, 22 Oct 2018 21:15:00 -0400tag:v4.chriskrycho.com,2018-10-22:/2018/scales-of-feedback-time-in-software-development.htmlsoftware developmenttestingprogramming languagesRustRust is Incredibly Productive for CLIshttp://v4.chriskrycho.com/2018/rust-is-incredibly-productive-for-clis.html<p>There are <em>reasons</em> I’m a Rust fanboy. One of them is the kind of thing I proved out to myself today—again, because I’ve had this experience before, albeit not with anything quite this “complicated.”</p> <p>I built <a href="https://github.com/chriskrycho/evernote2md">a little tool</a> in Rust to convert Evernote exports (in their custom <code>.enex</code> <abbr>XML</abbr> format) to Markdown files with <abbr>YAML</abbr> metadata headers—mostly just to see how quickly and effectively I could do it, because I’ve never actually had an excuse to use <a href="https://serde.rs">Serde</a> and I thought this might be a nice spot to try it.</p> <p>There’s a lot this little library <em>doesn’t</em> do. (Like include the creation and modification timestamps in the header, for example.) But all of those things would be <em>very</em> straightforward to do. I built this functioning little “script” in about two hours. For context: I’ve taken multiple passes at this in Python—which in the way people normally think about these things should be way <em>easier</em>—and I’ve failed both times.</p> <p>Rust’s compiler just helps you out <em>so much</em> along the way, not only with the type-checking but with the really amazing metaprogramming capabilities you get with it. Being able to slap <code>#[derive(Deserialize)]</code> on a struct and a couple attributes on struct fields and having it Just Work™ to deserialize XML into local types is mind-blowing. (The only thing I know of that’s playing the same game is F<sup>♯</sup> type-providers. I’d love to hear about similar capabilities in other languages!)</p> <p>I’m basically at the point where if I need a small command-line tool, I write it in Rust, <em>not</em> in a conventional scripting language like Python, because the benefits I get more than outweigh whatever small extra amount of mental overhead there is. And there’s not much of that mental overhead anyway for this kind of thing! As you can see <a href="https://github.com/chriskrycho/evernote2md/blob/master/src/main.rs#L71">in the actual code</a>, I make free and liberal use of <a href="https://doc.rust-lang.org/1.26.0/std/option/enum.Option.html"><code>expect</code></a> for this kind of tool.</p> <p>It’s also hard to oversell the ecosystem—even as relatively nascent as it is compared to some much older languages, the tools which exist are just really good. This project uses <a href="https://serde.rs">Serde</a> for deserializing from <abbr>XML</abbr> and serializing to <abbr>YAML</abbr>; <a href="https://github.com/rust-lang/regex">Regex</a>; <a href="https://clap.rs">Clap</a> for command line parsing; a nice little wrapper around <a href="https://pandoc.org">pandoc</a>; and, superpower even among superpowers, <a href="https://docs.rs/rayon/1.0.1/rayon/">Rayon</a>: free parallelization.</p> <p>Rust is, in short, <em>very productive</em> for things in this space. Far more than you might expect from the billing. Yes, it’s a “systems programming language” and you can write operating systems with it. But it’s also just a really great tool for <em>all sorts</em> of domains, including little <abbr>CLI</abbr> tools like this one.</p> Chris KrychoSun, 20 May 2018 08:35:00 -0400tag:v4.chriskrycho.com,2018-05-20:/2018/rust-is-incredibly-productive-for-clis.htmlRustprogramming languagesAesthetics and Programming Languageshttp://v4.chriskrycho.com/2018/aesthetics-and-programming-languages.html<p>My distaste for the aesthetics of C<sup>♯</sup> are fairly well known to people I talk to about programming languages—perhaps equally as well known as my love of Rust. So much so that both are running jokes among some of my colleagues and friends. My hypersensitivity to aesthetics both in general and also specifically in programming languages and work environment is <em>also</em> so well-known as to be a gag.</p> <p>But I was writing a bunch of Rust this weekend, and looking at it and thinking about it and wondering why it is that C<sup>♯</sup> drives me so up the wall aesthetically and experientially, while Rust doesn’t. On the surface, they don’t actually look all that different.</p> <p>Here’s <em>roughly</em> equivalent code in each:</p> <pre class="cs"><code>public class Person { public string Name { get; set; } = &quot;Chris&quot;; public void greet() { Console.WriteLine($&quot;Hello, {Name}&quot;); } }</code></pre> <pre class="rust"><code>struct Person { name: String, } impl Person { pub fn new() -&gt; Person { Person { name: String::from(&quot;Chris&quot;) } } pub fn greet(&amp;self) { println!(&quot;Hello, {}&quot;, self.name); } }</code></pre> <p>When you start tossing in generics and lifetimes, Rust can actually end up looking a <em>lot</em> messier than C<sup>♯</sup>.</p> <pre class="rust"><code>impl&lt;&#39;a, &#39;b, T, U&gt; SomeTrait&lt;&#39;a, U&gt; for SomeType&lt;&#39;b, U&gt; where T: SomeOtherTrait + YetAnotherTrait, U: OhWowSoManyTraits { fn some_trait_method(&amp;self) { // ... } }</code></pre> <p>Nothing about that is what I would call aesthetically beautiful in a general sense! There’s a <em>lot</em> of syntax.</p> <p>What I’ve concluded so far, though, is that my difference in feelings comes down to the way that syntax maps back to the underlying semantics, and my feelings about those underlying semantics. The basic language design approach C<sup>♯</sup> takes—i.e. everything is a class; mutation is both encouraged and implicit; don’t bother with value types—drives me batty. I don’t love the syntax, not least because it ends up being <em>so</em> verbose and noisy (you can express the same things in F<sup>♯</sup> much more briefly)—but also because I actively dislike the programming models it encourages (I don’t like the C<sup>♯</sup> programming model when I see in in F<sup>♯</sup> either!).</p> <p>Rust, by contrast, matches the way I <em>do</em> and <em>want to</em> think about the world. Mutability is allowed but neither actively encouraged nor actively discouraged; more to the point it’s <em>explicit</em>. Insofar as “shared mutable state is the root of all evil,” Rust has two legs up on C<sup>♯</sup>: it (a) doesn’t <em>allow</em> shared mutable state and (b) makes explicit where mutation <em>is</em> happening. It also separates data from behavior. It also has real value types. It also has sum types and pattern matching. In both cases, a lot of the syntactical noise is inessential, a holdover from the legacy of C; but in Rust’s case the way it maps onto a <em>programming model</em> that is more like OCaml than like C decreases the pain I feel from that noise.</p> <p>This <em>could</em> be taken to validate the idea that syntax doesn’t matter, that the underlying semantics are everything, but that’s not the case. It’s not that I <em>love</em> Rust’s syntax. It’s that, although I dislike it at times, it doesn’t rise to the level of frustration I feel in C<sup>♯</sup> because it’s not coupled to a programming model that I loathe. The syntax matters; it’s just not the <em>only</em> thing that matters.</p> <p>An interesting thing to consider: what Rust would look like in a world where it embraced its OCaml roots. (I don’t think Rust should have done this; spending its complexity budget on ideas instead of syntax was the right choice. But it’s still interesting.) The simplest level of translation might look something (very) roughly like this:</p> <pre class="haskell"><code>impl &#39;a &#39;b T U SomeTrait &#39;a T for SomeType &#39;b U where T : SomeOtherTrait + YetAnotherTrait some_trait_method :: &amp;self -&gt; void some_trait_method self = -- ...</code></pre> <p>This is obviously still a lot of syntax, but it’s all basically necessary given the things Rust is trying to express with lifetimes, ownership, etc.—and I did this off the top of my head with literally <em>no</em> consideration other than “what’s the most direct translation into roughly Haskell-ish syntax I can write?” It makes me genuinely curious where a language that aimed for Rust’s same kinds of guarantees but actively embracing the ML/Haskell family’s syntax might end up. I have a guess that I’d like it even better than I do Rust.</p> Chris KrychoSun, 13 May 2018 11:00:00 -0400tag:v4.chriskrycho.com,2018-05-13:/2018/aesthetics-and-programming-languages.htmlcsharprustprogramming languagesExploring 4 Languages: Integrity and Consistencyhttp://v4.chriskrycho.com/2018/exploring-4-languages-integrity-and-consistency.html<p>In chapter 6, Wlaschin turns to one of the most important aspects of “domain modeling”: keeping it consistent. It’s all well and good to set up a domain model, but if you don’t have a way to make sure that model is reliable everywhere you use it, well… you’ve done a lot of extra work and you’re not going to see a lot of results for all that effort! But as Wlaschin points out, we can actually use the type systems, and the types we wrote up in the previous chapter, to help us enforce the business <em>rules</em> for our domain (as well as the business <em>shapes</em> in the domain).</p> <p>An important note: you can see the latest version of this code (along with history indicating some of my travails in getting there!) in <a href="https://github.com/chriskrycho/dmmf">this public repository on GitHub</a>.</p> <section id="a-simple-example-widgetcode" class="level2"> <h2>A simple example: <code>WidgetCode</code></h2> <p>We’ll start with one of the simpler examples: validating that a <code>WidgetCode</code> is legitimate. A <code>WidgetCode</code>, in this domain, is valid if, and <em>only</em> if, it has a <code>W</code> followed by four digits.</p> <p>The basic tack we’ll take, in all four languages, is to leverage the way the types work to make it so we have to use a function to create a valid instance of a <code>WidgetCode</code>. That’s a bit of extra work (though especially in the functional-first languages, it ends up not being a <em>lot</em> of extra work) but it lets us use <code>Result</code> types to handle invalid data up front.</p> <p>The downside is that we can’t just get directly at the value inside our wrapper types using basic pattern matching. Instead, we need to be provide a function for “unwrapping” it. Tradeoffs!</p> <p>We’ll go at this using the most appropriate tool from each language, but in every case we’ll end up with a <code>create</code> function that takes a string and returns a <code>Result</code> with the successful option being a <code>WidgetCode</code> and the error option being a string describing the error; and a <code>value</code> function to unwrap a valid code. Throughout, I also assume an essentially-identical implementation of a related <code>GizmoCode</code> type; I pull both in to show how they end up being used side by side.</p> <section id="rust" class="level3"> <h3>Rust</h3> <p>We are using a tuple struct to wrap the string value here. Since there is no <code>pub</code> modifier in the wrapped <code>String</code>, it’s opaque from the perspective of the caller—and this is exactly what we want. We’ll pull in <a href="https://docs.rs/regex/0.2.10/regex/">the <code>Regex</code> crate</a> and validate the code passed to us on creation.</p> <pre class="rust"><code>use regex::Regex; pub struct WidgetCode(String); impl WidgetCode { pub fn create(code: &amp;str) -&gt; Result&lt;WidgetCode, String&gt; { let re = Regex::new(r&quot;W\d{4}&quot;).expect(r&quot;W\d{4} is a valid regex&quot;); if re.is_match(code) { Ok(WidgetCode(String::from(code))) } else { Err(String::from( &quot;`WidgetCode` must begin with a &#39;W&#39; and be followed by 4 digits&quot;, )) } } pub fn value(&amp;self) -&gt; &amp;str { &amp;self.0 } }</code></pre> <p>This is fairly idiomatic Rust: we’re <em>borrowing</em> a <em>reference</em> to the code as a “string slice”, and creating a new, wrapped <code>String</code> instance to wrap up the code <em>or</em> return a new <code>String</code> as an error. When we get the value out, we return a reference to the string,<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> with <code>&amp;self.0</code>: <code>&amp;</code> to indicate a reference, <code>.0</code> to indicate the first item of a tuple. Note as well that the final <code>if</code> block here is an expression. There’s no semicolon terminating it, and this whole <code>if</code> block ends up being the resulting value of the function.</p> <p>One other point of interest here is that the creation of the regex <em>itself</em> is checked by the compiler for us! If we pass an invalid regular expression, this simply won’t compile.</p> <p>This could also live in its own module, <code>ordering/widget_code.rs</code>, and in fact that’s how I would normally do this (and have in the repository where I’m working): every one of these small types would get its own module file within the containing <code>Ordering</code> module. It’s not <em>necessary</em>, but as the domain model grows, it becomes increasingly <em>convenient</em> in that you always know where to find things.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p> <p>Then we can import it and use it like this in <code>ordering/mod.rs</code>:</p> <pre class="rust"><code>mod widget_code; mod gizmo_code; use widget_code::WidgetCode; use gizmo_code::GizmoCode; pub enum ProductCode { Widget(WidgetCode), Gizmo(GizmoCode), } fn demo_it() { let valid = WidgetCode::create(&quot;W1234&quot;); let invalid = WidgetCode::create(&quot;wat&quot;); let unwrapped = match valid { Ok(ref code) =&gt; code.value(), Err(_) =&gt; &quot;&quot;, }; }</code></pre> <p>Notice that in Rust, the <code>mod.rs</code> file declares all child modules. If you had a <code>widget_code.rs</code> on the file system but no <code>mod widget_code;</code>, Rust would just ignore the declaration entirely. Then Rust also requires us to <code>use widget_code;</code> to access its contents. The distinction between declaring and using a given module makes some sense: by the time all is said and done with this exercise, we won’t be doing much of anything in this <code>Ordering</code> module; it’ll exist primarily as a grouping construct for all the <em>other</em> modules.</p> <p>In this case, we go ahead and import the <code>WidgetCode</code> type from the module. We only have the one type there, with no standalone functions: everything is attached to the type via the <code>impl</code> block; so we can just call everything directly off of the type. This ends up feeling <em>kind of</em> like the way we’d do things in a traditional OOP language, but also <em>really not</em>, because we still have a separation between the data type and the implementation of functionality attached to it. It’s not obvious <em>here</em>, but we could write <code>impl WidgetCode</code> in some <em>other</em> module in the crate, and as long as there’s no conflict between the implementations, it’s fine! And then we could call whatever function we defined in <em>that</em> block “on” <code>WidgetCode</code>. This is on the one hand <em>totally</em> unlike what we’ll see in the other languages, and on the other hand <em>weirdly analogous</em> to them.</p> <p>I’m going to pass over why we need <code>ref code</code> here, as it gets into details of Rust’s model of ownership and reference borrowing <em>and</em> it’s going to be unneeded because of improvements to Rust’s compiler fairly soon. The one thing to note here is that we get nice memory/allocation behavior, i.e. we’re not doing a bunch of separate heap string allocations here. This is one of the big upsides to Rust in general! It’s not quite as pretty as what we’ll see below, but the performance wins are awesome.</p> </section> <section id="elm" class="level3"> <h3>Elm</h3> <p>Elm introduces us to a pattern we’ll see in each of the more traditional “functional” languages: the use of <em>modules</em> for this kind of structure. First the code, then some comments on it:</p> <pre class="elm"><code>-- src/ordering/WidgetCode.elm module Ordering.WidgetCode exposing (WidgetCode, create, value) import Regex exposing (contains, regex) type WidgetCode = WidgetCode String create : String -&gt; Result String WidgetCode create code = if contains (regex &quot;W\\d{4}&quot;) code then Ok (WidgetCode code) else Err &quot;`WidgetCode` must begin with a &#39;W&#39; and be followed by 4 digits&quot; value : WidgetCode -&gt; String value (WidgetCode code) = code</code></pre> <p>Elm’s module system lets you choose exactly what to expose. In this case, we’re only exporting the type itself along the <code>create</code> and <code>value</code> functions—but, importantly, <em>not</em> the normal type constructors for the type.</p> <p>You can import the things exposed both as a module and as individual items. Assume we implemented <code>GizmoCode</code> the same way. We’d import and use them in <code>Ordering.elm</code> like this:</p> <pre class="elm"><code>-- Ordering.elm import Ordering.WidgetCode as WidgetCode exposing (WidgetCode) import Ordering.GizmoCode as GizmoCode exposing (GizmoCode) type ProductCode = Widget WidgetCode | Gizmo GizmoCode valid = WidgetCode.create &quot;W1234&quot; invalid = WidgetCode.create &quot;wat&quot; unwrapped = case valid of Result.Ok code -&gt; WidgetCode.value (code) Result.Err _ -&gt; &quot;&quot;</code></pre> <p>As with Rust, we can’t construct the type without using the provided function. As I’ve written the imports, you’d create a <code>WidgetCode</code> by writing <code>WidgetCode.create "W1234"</code>. You could also import it directly, but that would have its own problems once you had the <code>create</code> function imported for <code>GizmoCode</code> as well.</p> <p>Finally, notice the way we aliased the module name here with <code>as</code> on the import: we don’t have to write out the fully qualified path this way. And there’s no conflict between the aliased module name and the type name – they live in their own namespaces (as it should be!). Importing the type name distinctly is handy because it means we don’t have to write the body of the union type out as <code>Widget WidgetCode.WidgetCode</code>.</p> </section> <section id="f" class="level3"> <h3>F<sup>♯</sup></h3> <p>The F<sup>♯</sup> code looks a <em>lot</em> like the Elm code. The main differences here have to do with their module systems.</p> <pre class="fsharp"><code>namespace Ordering type WidgetCode = private WidgetCode of string module WidgetCode = let create code = if Regex.IsMatch(code, @&quot;W\d{4}&quot;) then Ok (WidgetCode code) else Error &quot;`WidgetCode` must begin with a &#39;W&#39; and be followed by 4 digits&quot; let value (WidgetCode code) = code</code></pre> <p>Here we declare that we’re in the <code>namespace Ordering</code>. Everything here will be publicly visible to everything <em>else</em> in the <code>namespace Ordering</code>. We could also make this a <code>module</code>, and in that case we’d need to explicitly open it in other modules. Because it’s part of the base namespace we’re using for <code>Ordering</code>, though, we get it for “free”. There’s a downside to this, though. More on that below.</p> <p>Also notice that this means that we have yet one more “namespace” for names to live in: <code>namespace</code> names are different from <code>module</code> are different from type names! So here we declare a top-level <code>module Ordering</code> here so that we can actually write code that <em>does something</em> in the file – <code>namespace</code>s can only contain type definitions (including <code>module</code> definitions).</p> <pre class="fsharp"><code>namespace Ordering type ProductCode = | Widget of WidgetCode | Gizmo of GizmoCode module DemoIt = let valid = WidgetCode.create &quot;W1234&quot; let invalid = WidgetCode.create &quot;wat&quot; let unwrapped = match valid with | Ok(code) -&gt; WidgetCode.value code | Error(_) -&gt; &quot;&quot;</code></pre> <p>The things to notice here as particularly different from the others:</p> <ol type="1"> <li>We don’t have to explicitly import the module names, because we used the same namespace (<code>Ordering</code>) to group them. We could also have done <code>namespace Ordering.WidgetCode</code> and <code>open Ordering.WidgetCode</code>; that might actually make more or less sense in the context. I <em>think</em> this is probably more idiomatic, however, which is why I picked it.</li> <li>Since we’re keeping the rest of the containing module in the same namespace, we <em>do</em> have to declare <code>module DemoIt</code> for functionality – not just types – to live in. This is true for both <code>Ordering.fs</code> and <code>WidgetCode.fs</code> and so on.</li> </ol> <p>This way of structuring things works really well, but it has one major downside compared to Elm and Rust: where any given name comes from is <em>not</em> obvious from any given text file. Using modules instead of namespaces and using more fully qualified names <em>could</em> help here, but the reality is simply that F<sup>♯</sup> (like C<sup>♯</sup>) basically leaves you out to dry here. My take is that this is basically what happens when you design a language <em>assuming</em> IDE-like tooling. But especially when looking at e.g. GitHub diff views, or just browsing source code in general, I strongly prefer the way Elm and Rust generally lead you to do explicit imports or fully qualified paths. (Both have an escape hatch: Rust’s <code>use path::to::module::*;</code> and Elm’s <code>import Path.To.Module exposing (..)</code>, but both are actively discouraged as bad practice in <em>most</em> situations.)</p> </section> <section id="reason" class="level3"> <h3>Reason</h3> <p>Interestingly, Reason <em>looks</em> most like Rust but <em>behaves</em> most like F<sup>♯</sup>. The biggest difference is that I need a separate <em>interface file</em> for Reason to get the privacy benefits that I’m getting in all the other languages.</p> <p>We put the definition file at <code>ordering/Ordering_WidgetCode.rei</code>. (I’ll comment on the long name in a moment.)</p> <pre class="reason"><code>type gizmoCode = pri | GizmoCode(string); let create: string =&gt; Js.Result.t(widgetCode, string); let value: widgetCode =&gt; string;</code></pre> <p>With that module definition in place, we can separately supply the implementation, in <code>ordering/Ordering_WidgetCode.re</code>.</p> <pre class="reason"><code>type widgetCode = | WidgetCode(string); let create = code =&gt; { let isMatch = Js.Re.fromString(&quot;W\\d{4}&quot;) |&gt; Js.Re.exec(code) |&gt; Js.Option.isSome; if (isMatch) { Js.Result.Ok(WidgetCode(code)); } else { Js.Result.Error( &quot;`WidgetCode` must begin with a &#39;W&#39; and be followed by 4 digits&quot; ); }; }; let value = (WidgetCode(code)) =&gt; code;</code></pre> <p>Note that you could do the same thing with an interface file for F<sup>♯</sup>. We’re also doing something that’s similar in principle to the use of private types in in F<sup>♯</sup>, but unlike in F<sup>♯</sup> we <em>have</em> to use the module interface to make it work as far as I can tell. The <em>interface</em> can declare the type private, but in the actual implementation, the type has to be non-private to be constructable. (If I’m wrong, please send me a note to let me know! But that’s what I gathered from reading OCaml docs, as well as from command line error messages as I played around.) Also, the fact that Reason has landed on the keyword <code>pri</code> instead of OCaml and F<sup>♯</sup>’s much saner <code>private</code> is super weird.</p> <p>The interface file just defines the types, and has the <code>.rei</code> extension. <code>type widgetCode</code> here is an <em>abstract</em> type, which provides no information about what it contains. Note the function types are provided as well. Here I’m using specifically the <code>Js.Result</code> type; there is also a <code>Result</code> type in at least one of the OCaml standard libraries. This is one of the more complicated things about Reason compared to the others: there are… <em>several</em> standard libraries to choose from, which will or won’t work differently depending on what compile target you’re picking.</p> <p>In any case, once we have both the module and the implementation defined, we can use it like this in <code>ordering.re</code>:</p> <pre class="reason"><code>module WidgetCode = Ordering_WidgetCode; module GizmoCode = Ordering_GizmoCode; open WidgetCode; open GizmoCode; type productCode = | Widget(widgetCode) | Gizmo(gizmoCode); let valid = WidgetCode.create(&quot;W1234&quot;); let invalid = WidgetCode.create(&quot;wat&quot;); let unwrapped = switch valid { | Js.Result.Ok(code) =&gt; WidgetCode.value(code) | Js.Result.Error(_) =&gt; &quot;&quot; };</code></pre> <p>We do this mapping from <code>Ordering_WidgetCode</code> to <code>WidgetCode</code> here because OCaml and therefore Reason has only a single global namespace for its module names as defined by the file system. You can nest modules, but only <em>within</em> files. The workaround is, well… <code>Ordering_</code> and remapping the name as we have here. This lets you access the nested modules as <code>Ordering.WidgetCode</code> and so on elsewhere.</p> <p>Then we <code>open WidgetCode</code> etc. so that we can write <code>widgetCode</code> instead of <code>WidgetCode.widgetCode</code> in the <code>productCode</code> definition. This is basically the same effect we get from just being in the same <code>namespace</code> in F<sup>♯</sup> (which, again, we could rewrite exactly this way), or from the kinds of imports we discussed above for Rust and Elm.</p> </section> </section> <section id="numeric-validation-unitquantity" class="level2"> <h2>Numeric validation: <code>UnitQuantity</code></h2> <p>So far, the showing tilts <em>heavily</em> in F<sup>♯</sup>’s and Elm’s favor in terms of expressiveness and elegance. However, there’s a lot of variation depending on exactly what you’re doing. If, for example, you want to validate a <em>range</em>, well… then Rust actually has a pretty good approach! Once again, you’ll note that these all have a lot in common; the difference mostly comes down to the degree of syntactical noise required to express the same basic thing.</p> <p>In this section, I’m not really going to spend a lot of time discussing the details and differences; I’m just leaving it here to show an interesting example where the languages’ design decisions end up have slightly different ergonomic tradeoffs.</p> <section id="rust-1" class="level3"> <h3>Rust</h3> <pre class="rust"><code>// ordering/unit_quantity.rs pub struct UnitQuantity(u32); impl UnitQuantity { pub fn create(qty: u32) -&gt; Result&lt;UnitQuantity, String&gt; { match qty { 0 =&gt; Err(String::from(&quot;`UnitQuantity` cannot be less than 1&quot;)), 1...1000 =&gt; Ok(UnitQuantity(qty)), _ =&gt; Err(String::from(&quot;`UnitQuantity` cannot be greater than 1000&quot;)), } } pub fn value(&amp;self) -&gt; u32 { self.0 } pub fn minimum() -&gt; UnitQuantity { UnitQuantity(1) } }</code></pre> </section> <section id="elm-1" class="level3"> <h3>Elm</h3> <pre class="elm"><code>-- ordering/UnitQuantity.elm module Ordering.UnitQuantity exposing (UnitQuantity, create, value) type UnitQuantity = UnitQuantity Int create : Int -&gt; Result String UnitQuantity create qty = if qty &lt; 1 then Err &quot;`UnitQuantity` cannot be less than 1&quot; else if qty &gt; 1000 then Err &quot;`UnitQuantity` cannot be greater than 1000&quot; else Ok (UnitQuantity qty) value : UnitQuantity -&gt; Int value (UnitQuantity qty) = qty minimum : UnitQuantity minimum = UnitQuantity 1</code></pre> </section> <section id="f-1" class="level3"> <h3>F<sup>♯</sup></h3> <pre class="fsharp"><code>// ordering/UnitQuantity.fs namespace Ordering type UnitQuantity = private UnitQuantity of uint32 module UnitQuantity = let create qty = if qty &lt; 1u then Error &quot;`UnitQuantity` cannot be less than 1&quot; else if qty &gt; 1000u then Error &quot;`UnitQuantity` cannot be greater than 1000&quot; else Ok (UnitQuantity qty) let value (UnitQuantity qty) = qty let minimum = UnitQuantity 1</code></pre> </section> <section id="reason-1" class="level3"> <h3>Reason</h3> <pre class="reason"><code>/* ordering/Ordering_UnitQuantity.rei */ type unitQuantity = pri | UnitQuantity(int); let create: int =&gt; Js.Result.t(unitQuantity, string); let value: unitQuantity =&gt; int; let minimum: unitQuantity;</code></pre> <pre class="reason"><code>/* ordering/Ordering_UnitQuantity.re */ type unitQuantity = | UnitQuantity(int); let create = qty =&gt; if (qty &lt; 1) { Js.Result.Error(&quot;`UnitQuantity` cannot be less than 1&quot;); } else if (qty &gt; 1000) { Js.Result.Error(&quot;`UnitQuantity` cannot be greater than 1000&quot;); } else { Js.Result.Ok(UnitQuantity(qty)); }; let value = (UnitQuantity(qty)) =&gt; qty; let minimum = UnitQuantity(1);</code></pre> </section> </section> <section id="aside-on-documentation" class="level2"> <h2>Aside: On Documentation</h2> <p>One thing that became <em>extremely</em> clear in the course of working all of this out is that the documentation stories for these languages are in vastly, <em>vastly</em> different places.</p> <p>Figuring out how to write this private <code>create</code>/<code>value</code> approach was <em>very</em> straightforward in Rust, because it’s literally just right there in how <code>impl</code> blocks and the <code>pub</code> keyword work: things default to private, including the contents of a struct, and you <em>always</em> define the related functionality with <code>pub fn</code> declarations in the related <code>impl</code> block.</p> <p>Elm and F<sup>♯</sup> were both slightly harder, in that I had to poke around a bit to figure out the right way to do it. But not <em>that</em> much harder. Both use module-level isolation to accomplish this; the main difference there was that F<sup>♯</sup> just lets you do it inline and Elm explicitly ties modules to files.</p> <p>Reason… was very, <em>very</em> difficult to get sorted out. This is just a function of the state of the ecosystem. Reason is <em>distinct syntax</em> for OCaml, but it also leans on BuckleScript. That means that if you want to figure out how to do anything, you probably need to search in the docs for all of those, and if your answer turns out to come from OCaml then you have to figure out how to translate it back into Reason and BuckleScript! Ultimately, I was able to figure it out and get the project layout to how you see it in the repository, but… it took a lot more digging than with any of the other projects!</p> </section> <section id="summary" class="level2"> <h2>Summary</h2> <p>As with our <a href="http://v4.chriskrycho.com/2018/exploring-4-languages-starting-to-model-the-domain.html">previous foray</a>, we can see a ton of similarities across these languages. All lean heavily on pattern-matching for dealing with different scenarios; all let us make use of a <code>Result</code> type for handling success or failure; all make heavy use of expression-bodied-ness; and all supply <em>some</em> way to make types constructable only in safe/controlled ways.</p> <p>For Rust, that’s a matter of leaving the internals of a <code>struct</code> private and making <code>pub fn</code> helpers to do the construction and value retrieval. For Elm, F<sup>♯</sup>, and Reason, that’s a matter of having the normal type <em>constructors</em> be private while exposing the types themselves normally. They do that in different ways (F<sup>♯</sup>’s <code>private type</code>, Elm’s <code>exposing</code>, and Reason’s <code>pri</code> annotation on the type variant in a module interface file), but the effect is essentially identical, and functionally equivalent to what we see in Rust.</p> <p>The main differences we see across Elm, F<sup>♯</sup>, and Reason have to do with the nature of the various module systems. In a lot of ways, Reason’s is the least capable <em>for this specific purpose</em>, because it’s directly tied to OCaml’s module system, which substantially predates any of the others. (I say “in a lot of ways” because OCaml’s modules are surprisingly capable; they end up being their own kind of types and you can do some crazy things with them, all of which I’d like to actually come to understand… eventually.) Rust’s module system, meanwhile, has a lot of similarities to Elm’s in particular, but because we actually carry functions along with the types they <code>impl</code> (though they get defined separately, with all the power that entails), we have a bit less boilerplate we need to write just to get at the specific functions in play.</p> <p>Next time (probably only a couple of weeks away because we’re working through the book at work in a book club!), I’ll be looking at Chapter 7: Modeling Workflows as Pipelines. I suspect this will be a place where the true functional orientation of Elm, F<sup>♯</sup>, and Reason will much more sharply differentiate them from the sometimes-functionalish-but-not-actually-functional way we write things in Rust.</p> </section> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>This reference will live and be valid as long as the underlying <code>WidgetCode</code> is. We could also return a <code>String</code> if we wanted that value to live independently of the <code>WidgetCode</code> instance backing it.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn2" role="doc-endnote"><p>Putting it in its own module, whether in a separate <em>does</em> have implications for privacy, though we don’t much care about them in this case. Rust lets us set the privacy on <a href="https://doc.rust-lang.org/1.24.1/reference/visibility-and-privacy.html">a whole spectrum</a>, from “visible everywhere” to “only visible in this specific module.”<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoSat, 24 Mar 2018 22:00:00 -0400tag:v4.chriskrycho.com,2018-03-24:/2018/exploring-4-languages-integrity-and-consistency.htmlfunctional programmingrustelmfsharpreasonmldomain-driven designfour-languagesExploring 4 Languages: Starting to Model the Domainhttp://v4.chriskrycho.com/2018/exploring-4-languages-starting-to-model-the-domain.html<p>In the first three chapters of <em>Domain Modeling Made Functional</em>, Wlaschin walks through the creation of a “domain model” for an order-taking system. (It’s well worth reading the book just for a bunch of the lessons in that section—I found them quite helpful!) Then, after spending a chapter introducing F<sup>♯</sup>’s type system, he introduces the ways you can <em>use</em> those type mechanics to express the domain. In today’s post, I’ll show the idiomatic implementations of these types in each of Rust, Elm, F<sup>♯</sup>, and ReasonML.</p> <section id="simple-values" class="level2"> <h2>Simple values</h2> <p>Simple wrapper types let you take simple types like strings, numbers, etc. and use types to represent part of the business domain you’re dealing with—the basic idea being that a Customer ID may be a number, but it’s not interchangeable with <em>other</em> numbers such as Order IDs.</p> <p>Here’s the most ergonomic and effective (and automatically-formatted in line with the language standards, where applicable!) way to do that in each of the languages:</p> <p>Rust:</p> <pre class="rust"><code>struct CustomerId(i32);</code></pre> <p>Elm:</p> <pre class="elm"><code>type CustomerId = CustomerId Int</code></pre> <p>F<sup>♯</sup>:</p> <pre class="fsharp"><code>type CustomerId = CustomerId of int</code></pre> <p>ReasonML:</p> <pre class="reason"><code>type customerId = | CustomerId(int);</code></pre> <p>Note how similar these all are! The Rust implementation is the <em>most</em> distinctive, though you can do it with the same kind of union type as the others. Here’s how that would look:</p> <pre class="rust"><code>enum CustomerId { CustomerId(i32), }</code></pre> <p>For performance reasons, you might also choose to implement the F<sup>♯</sup> type as a struct:</p> <pre class="fsharp"><code>&lt;Struct&gt; type CustomerId = CustomerId of int</code></pre> </section> <section id="complex-data" class="level2"> <h2>Complex data</h2> <p>Wlaschin then moves on to showing how to model more complex data structures: types that “and” or “or” together other data. We “and” data together using record or struct types, and “or” data together using “union” or “enum” types. (Assume we’ve defined <code>CustomerInfo</code>, <code>ShippingAddress</code>, etc. types for all of these.)</p> <p>Rust:</p> <pre class="rust"><code>// &quot;and&quot; struct Order { customer_info: CustomerInfo, shipping_address: ShippingAddress, billing_address: BillingAddress, order_lines: Vec&lt;OrderLine&gt;, billing_amount: BillingAmount, } // &quot;or&quot; enum ProductCode { Widget(WidgetCode), Gizmo(GizmoCode), }</code></pre> <p>Elm:</p> <pre class="elm"><code>-- &quot;and&quot; type alias Order = { customerInfo : CustomerInfo , shippingAddress : ShippingAddress , billingAddress : BillingAddress , orderLines : List OrderLine , billingAmount : BillingAmount } -- &quot;or&quot; type ProductCode = Widget WidgetCode | Gizmo GizmoCode</code></pre> <p>F<sup>♯</sup>:</p> <pre class="fsharp"><code>// &quot;and&quot; type Order = { CustomerInfo : CustomerInfo ShippingAddress : ShippingAddress BillingAddress : BillingAddress OrderLines : OrderLine list AmountToBill: BillingAmount } // &quot;or&quot; type ProductCode = | Widget of WidgetCode | Gizmo of GizmoCode</code></pre> <p>ReasonML—note that since we’re assuming we’ve already defined the other types here, you can write this without duplicating the name and type declaration, just like you can with JavaScript object properties.</p> <pre class="reason"><code>/* &quot;and&quot; */ type order = { customerInfo, shippingAddress, billingAddress, orderLine, billingAmount }; /* &quot;or&quot; */ type productCode = | Widget(widgetCode) | Gizmo(gizmoCode);</code></pre> <p>An interesting aside: unless you planned to reuse these types, you wouldn’t usually write these as standalone types with this many wrapper types in it in Rust in particular (even if the compiler would often recognize that it could squash them down for you).<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> Instead, you’d normally write <em>only</em> the base enum type to start, and refactor out the <code>struct</code> wrapper later only if you found you needed it elsewhere:</p> <pre class="diff"><code>enum ProductCode { - Widget(WidgetCode), + Widget(String), - Gizmo(GizmoCode), + Gizmo(String), }</code></pre> <p>That said: given how the book is tackling things, and the fact that you might want to <em>validate</em> these types… having them as these low-cost wrappers is probably worth it. (In fact, having read a bit further than I’ve managed to write out yet, I can guarantee it.)</p> <p>We work through the rest of the basic types this way. But what about the types where we don’t yet have a good idea how we want to handle them?</p> <p>Each of these languages gives us an out (or more than one) for how to say “I don’t know what to put here yet.”</p> <p>Rust (which does not have a built-in <code>Never</code> type… yet; see below):</p> <pre class="rust"><code>// Make an empty enum (which you by definition cannot construct) enum Never {} // Use it throughout where we don&#39;t know the type yet. It will fail to compile // anywhere we try to *use* this, because you can&#39;t construct it. type OrderId = Never;</code></pre> <p>Elm (which has a built-in <code>Never</code> type):</p> <pre class="elm"><code>-- It will fail to compile anywhere we try to *use* this, because you cannot -- construct `Never`. type alias OrderId = Never</code></pre> <p>F<sup>♯</sup> (which <em>sort</em> of does):</p> <pre class="fsharp"><code>// Make a convenience type for the `exn`/`System.Exception` type type Undefined = exn type OrderId = Undefined</code></pre> <p>Reason (which also <em>sort</em> of does—identically with F<sup>♯</sup>):</p> <pre class="reason"><code>/* Make a convenience type for the `exn`/`System.Exception` type */ type undefined = exn; /* Use it throughout where we don&#39;t know the type yet. It will compile, but fail to run anywhere we try to *use* this. */ type orderId = undefined;</code></pre> <p>For both F<sup>♯</sup> and Reason, that’s following Wlaschin’s example. The main reason to do that is to make explicit that we’re not actually wanting an <em>exception</em> type in our domain model, but just something we haven’t <em>yet</em> defined. Anywhere we attempted to use it, we’d have to handle it like, well… an exception, instead of an actual type.</p> <pre class="rust"><code>type OrderId = !;</code></pre> </section> <section id="workflows-and-functions" class="level2"> <h2>Workflows and functions</h2> <p>Once we have the basic types themselves in place, we need to write down the ways we transform between them. In a functional style, we’re not going to implement instance methods—though as we’ll see in the next post, what we do in Rust will have <em>some</em> similarities to class methods—we’re going to implement standalone functions which take types and return other types.</p> <p>Again, you’ll note that despite the common lineage, there is a fair amount of variation here. (Note that we’d also have defined the <code>UnvalidatedOrder</code>, <code>ValidationError</code>, and <code>ValidatedOrder</code> types for all of this; I’m mostly interested in showing <em>new</em> differences here.)</p> <p>Rust (using the <a href="https://github.com/alexcrichton/futures-rs">Futures</a> library to represent eventual computation):</p> <pre class="rust"><code>type ValidationResponse&lt;T&gt; = Future&lt;Item = T, Error = ValidationError&gt;; fn validate_order(unvalidated: UnvalidatedOrder) -&gt; Box&lt;ValidationResponse&lt;ValidatedOrder&gt;&gt; { unimplemented!() }</code></pre> <p>Elm (using the built-in <code>Task</code> type for eventual computation; <code>Task</code>s encapsulate both eventuality and the possibility of failure):</p> <pre class="elm"><code>type ValidationResponse a = Task (List ValidationError) a type alias ValidateOrder = UnvalidatedOrder -&gt; ValidationResponse ValidatedOrder</code></pre> <p>F<sup>♯</sup> (using the built-in <code>Async</code> type for eventual computation):</p> <pre class="fsharp"><code>type ValidationResponse&lt;&#39;a&gt; = Async&lt;Result&lt;&#39;a,ValidationError list&gt;&gt; type ValidateOrder = UnvalidatedOrder -&gt; ValidationResponse&lt;ValidatedOrder&gt;</code></pre> <p>Reason (using the built-in JavaScript-specific <code>Js.Promise</code> type—which is exactly what it sounds like—for eventual computation):</p> <pre class="reason"><code>type validationResponse(&#39;a) = Js.Promise.t(Js.Result.t(&#39;a, list(validationError))); type validateOrder = unvalidatedOrder =&gt; validationResponse(validatedOrder);</code></pre> <p>Once again Rust is much <em>more</em> different here from the others than they are from each other. The biggest difference between Elm, F<sup>♯</sup>, and Reason is how they handle generics and type parameters.</p> <p>You’ll note that in Elm, they just follow the name of the wrapping type. This is a kind of syntactic symmetry: the way you <em>name</em> a generic type like this is the same basic way you <em>construct</em> it. It’s quite elegant. And as it turns out, the same is true of Reason; it’s just that its authors have chosen to follow OCaml and use parentheses for them instead of following Haskell with spaces—a reasonable choice, given Reason is surface syntax for OCaml and not Haskell.</p> <p>F<sup>♯</sup> uses angle brackets, I strongly suspect, because that’s what C<sup>#</sup> uses for generics, and keeping them syntactically aligned in things like this is very helpful. Rust similarly uses angle brackets for similarity with other languages which have similar surface syntax—especially C++ (with its templates).</p> <p>The way you <em>name</em> generic parameters differs between the languages as well. Elm, following Haskell, uses lowercase letters to name its generics (usually called <em>type parameters</em> in Elm). F<sup>#</sup> and Reason both (unsurprisingly) follow OCaml in using lowercase letters preceded by an apostrophe to name generics—in F<sup>#</sup>, <code>TypeGenericOver&lt;'a&gt;</code>; in Reason, <code>typeGenericOver('a)</code>. Rust follows the convention from languages like C++, Java, and C<sup>#</sup> and uses capital letters, <code>TypeGenericOver&lt;T&gt;</code>. The use of specific letters is conventional, not mandated by the language (unlike the casing). The ML family usually starts with <code>a</code> and moves through the alphabet; Rust and the languages it follows usually start with <code>T</code> (for <em>type</em>) and moves forward through the alphabet. (Sometimes you’ll also see different letters where it’s obviously a better fit for what’s contained.)</p> <p>These languages also vary in the syntax for constructing a <em>list</em> of things. In F<sup>#</sup> has convenience syntax for a few built-ins (the most common being the <code>List</code> and <code>Option</code> types), allowing you to write them <em>either</em> as e.g. <code>List&lt;ConcreteType&gt;</code> or <code>ConcreteType list</code> (as here in the example). Elm, Reason, and Rust all just use the standard syntax for generic types—<code>List a</code>, <code>list('a)</code>, and <code>Vec&lt;T&gt;</code> respectively.</p> <p>Finally, you’ll also note that we haven’t written out a <em>type</em> declaration here for Rust; we’ve actually written out a stub of a function, with the <a href="https://doc.rust-lang.org/std/macro.unimplemented.html"><code>unimplemented!()</code></a> <a href="https://doc.rust-lang.org/1.17.0/reference/macros-by-example.html">macro</a>. If you invoke this function, you’ll get a clear crash with an explanation of which function isn’t implemented.</p> <p>Now, Rust also <em>does</em> let us write out the type of these functions as type aliases if we want:</p> <pre class="rust"><code>type ValidateOrder = Fn(UnvalidatedOrder) -&gt; Box&lt;ValidationResponse&lt;ValidatedOrder&gt;&gt;;</code></pre> <p>You just don’t use these very often in idiomatic Rust; it’s much more conventional to simply write out what I did above. However, the one time you <em>might</em> use a type alias like this is when you’re defining the type of a closure and you don’t want to write it inline. This is a pretty sharp difference between Rust and the other languages on display here, and it goes to the difference in their approaches.</p> <p>Rust is <em>not</em> a functional-first language in the way that each of the others are, though it certainly draws heavily on ideas from functional programming throughout and makes quite a few affordances for a functional style. Instead, it’s a programming language first and foremost interested in combining the most screaming performance possible with true safety, and leaning on ideas from the ML family (among others!) as part of achieving that.</p> <p>Among other things, this is why you don’t have currying or partial application in Rust: those essentially <em>require</em> you to have invisible heap-allocation to be ergonomic. We <em>don’t</em> have that in Rust, as we do in Elm, Reason, and F<sup>♯</sup>. If we want to pass around a function, we have to explicitly wrap it in a pointer to hand it around if we construct it in another function. (I won’t go into more of the details of this here; I’ve covered it some <a href="http://www.newrustacean.com/show_notes/e004/index.html">on New Rustacean</a> and some <a href="http://v4.chriskrycho.com/2015/rust-and-swift-viii.html">in my Rust and Swift comparison</a> a couple years ago.)</p> <p>That same underlying focus on performance and explicitness is the reason we have <code>Box&lt;ValidationResponse&lt;ValidatedOrder&gt;&gt;</code> in the Rust case: we’re explicitly returning a <em>pointer</em> to the type here. In Elm, F<sup>♯</sup>, and Reason, that’s <em>always</em> the case. But in Rust, you can and often do return stack-allocated data and rely on “move” semantics to copy or alias it properly under the hood.</p> </section> <section id="summary" class="level2"> <h2>Summary</h2> <p>So: lots of similarities here at first blush. The biggest differences that show up at this point are purely syntactical, other than some mildly sharper differences with Rust because of its focus on performance. The fact that these languages share a common lineage means it’s not hard to read any of them if you’re familiar with the others, and it’s actually quite easy to switch between them at the levels of both syntax and semantics.</p> <p>As usual, when dealing with languages in a relatively similar family, it’s <em>most</em> difficult to learn the <em>library</em> differences. The most obvious example of that here is Reason’s <code>Js.Promise</code>, Elm’s <code>Task</code>, F<sup>♯</sup>’s <code>Async</code>, and Rust’s <code>Future</code> types: each of those has their own quirks, their own associated helper functions or methods, and their own ways of handling the same basic patterns.</p> <p>Still, if you have played with any one of these, you could pretty easily pick up one of the others. It’s sort of like switching between Python and Ruby: there are some real differences there, but the similarities are greater than the differences. Indeed, if anything, these languages are <em>more</em> similar than those.</p> <p>Next time I’ll dig into Wlaschin’s chapter on <em>validating</em> the domain model, and here some of the not-just-syntax-level differences in the languages will start to become more apparent.</p> </section> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>I can’t speak to what’s idiomatic this way in any of the non-Rust languages, because I just haven’t used them enough yet.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoSun, 14 Jan 2018 09:00:00 -0500tag:v4.chriskrycho.com,2018-01-14:/2018/exploring-4-languages-starting-to-model-the-domain.htmlfunctional programmingrustelmfsharpreasonmldomain-driven designfour-languagesExploring 4 Languages: Project Setuphttp://v4.chriskrycho.com/2018/exploring-4-languages-project-setup.html<p>In this post, I’m just going to briefly talk through the steps I needed to do to set up each of the languages and my editor setup for them. Gladly, it was pretty simple. At the end, I’ll offer a note on my thoughts on the setup processes. (Note that this isn’t “How to do this for anyone ever”—it’s “how I did it, with some notes where it might be relevant to you.”)</p> <p>For context, I’m running macOS and using <a href="https://code.visualstudio.com">VS Code</a> as my editor. Whenever I say “Install the VS Code extension,” you can do it either by opening the extension side panel and searching for <code>&lt;Extension Name&gt;</code>, or by typing <code>ext install &lt;extension label&gt;</code>—I’ll write it like <code>&lt;Extension Name&gt;</code>/<code>&lt;extension label&gt;</code>.</p> <p>The source code as of what I’m describing in this post is <a href="https://github.com/chriskrycho/dmmf/tree/project-setup">at the <code>project-setup</code> tag</a> in <a href="https://github.com/chriskrycho/dmmf/">the repo</a>.</p> <section id="rust" class="level2"> <h2>Rust</h2> <ul> <li><strong>Language installation:</strong> Install <a href="https://rustup.rs"><em>rustup</em></a>: <code>curl https://sh.rustup.rs -sSf | sh</code><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>.</li> <li><strong>Editor setup:</strong> Installed the VS Code extension: <code>Rust (rls)</code>/<code>rust</code>.</li> <li><strong>Project setup:</strong> In the root of <a href="https://github.com/chriskrycho/dmmf">my repo</a>, I ran <code>cargo new rust</code>.</li> </ul> </section> <section id="elm" class="level2"> <h2>Elm</h2> <ul> <li><strong>Language installation</strong>: There are installers, but I just did <code>npm i -g elm</code>.</li> <li><strong>Editor setup:</strong> Installed the VS Code Elm extension: <code>Elm</code>/<code>elm</code>.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></li> <li><strong>Project setup:</strong> <ul> <li>Install the <code>create-elm-app</code> tool: <code>npm i -g create-elm-app</code></li> <li>In the root of the project, I ran <code>create-elm-app elm</code>.</li> </ul></li> </ul> </section> <section id="f" class="level2"> <h2>F<sup>♯</sup></h2> <ul> <li><strong>Language installation</strong>: Install <a href="http://www.mono-project.com">mono</a>: <code>brew install mono</code> (note installation instructions <a href="option-5-install-f-with-mono-via-homebrew-64-bit">here</a>).</li> <li><strong>Editor setup:</strong> Install the VS Code Ionide extension: <code>Ionide-fsharp</code>/<code>ionide-fsharp</code>. It’ll automatically install the associated Paket and FAKE extensions from the Ionide project as well, and those will install Paket and FAKE during installation.</li> <li><strong>Project setup:</strong> <ul> <li>In the root of the repo, I created the <code>fsharp</code> directory.</li> <li>Then I opened a VS Code instance to to that directory, opened the command palette, and ran <code>F#: New Project</code>. <ul> <li>I chose <code>console</code></li> <li>I left the directory blank</li> <li>I named the project <code>dmmf</code> (for <em>D</em>omain <em>M</em>odeling <em>M</em>ade <em>F</em>unctional).</li> <li>Since F<sup>♯</sup> (like C<sup>♯</sup>) prefers PascalCase names, I renamed the generated module <code>DMMF</code>.</li> </ul></li> </ul></li> </ul> </section> <section id="reasonml" class="level2"> <h2>ReasonML</h2> <ul> <li><strong>Language installation</strong>: Following the setup instructions <a href="https://reasonml.github.io/guide/javascript/quickstart">here</a>, I ran <code>npm install -g bs-platform</code>.</li> <li><strong>Editor setup:</strong> following <a href="https://reasonml.github.io/guide/editor-tools/global-installation">the official instructions</a>— <ul> <li>I ran <code>npm install -g https://github.com/reasonml/reason-cli/archive/3.0.4-bin-darwin.tar.gz</code> to install the dependencies for the editor configuration.</li> <li>I installed the VS Code extension: <code>Reason</code>/<code>reasonml</code>.</li> </ul></li> <li><strong>Project setup:</strong> In the root of the repo, I ran <code>bsb -init reason -theme basic-reason</code>.</li> </ul> </section> <section id="comments-on-the-setup-processes" class="level2"> <h2>Comments on the setup processes</h2> <p>Most of the languages have <em>fairly</em> straightforward processes to get up and running with a good-to-excellent tooling experience.</p> <p>The best of them is Rust, which is <em>extremely</em> easy to get up and running with.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> Elm is roughly in the middle—it’s less straightforward than Rust in that <code>create-elm-app</code> is <em>not</em> an officially supported approach, unlike <code>rustup</code> and <code>cargo</code>, so you’re going to have a much less awesome experience if you don’t know about it.</p> <p>Reason and F<sup>♯</sup> both have slightly larger negatives.</p> <p>Reason requires you to <code>npm install</code> a large, gzipped file with multiple dependencies all bundled, instead of having a dedicated installer <em>a la</em> <code>rustup</code>. It also has the possibility for a not-so-great first-run experience in the editor, which <a href="https://github.com/facebook/reason/issues/1729">I discovered</a> all too quickly.</p> <p>F<sup>♯</sup> essentially requires you to use an editor extension to get the language setup with <a href="https://fsprojects.github.io/Paket/">Paket</a>, which is a <em>much</em> better choice of package manager than the default .NET package manager NuGet. Command line tools exist and are improving rapidly, and you <em>can</em> <a href="https://fsprojects.github.io/Paket/paket-and-dotnet-cli.html">get them working</a>… but it’s harder than it needs to be. And that project setup wizard is <em>fine</em>, but it’s a lot noisier than just doing <code>create-elm-app</code> or especially <code>cargo new</code>.</p> <p>In any case, though, I have them all up and running now! More soon!</p> </section> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>If you’re uncomfortable with running that script, there are <a href="https://www.rust-lang.org/en-US/other-installers.html">other options</a> as well.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn2" role="doc-endnote"><p>Note that the VS Code extension is <em>not</em> the best experience out there for Elm: the Atom extensions (<a href="https://atom.io/packages/language-elm">language-elm</a> and <a href="https://atom.io/packages/elmjutsu">elmjutsu</a>) are. I stuck with VS Code because it’s <em>good enough</em> and, more importantly, the Code extensions are arguably best in class for the <em>other</em> languages… and it’s what I use every day.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn3" role="doc-endnote"><p>I’m not just saying that because I’m a Rust fanboy, either! If Rust were hard to use, I’d be complaining <em>louder</em> because of my enthusiasm for the language.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoMon, 01 Jan 2018 13:00:00 -0500tag:v4.chriskrycho.com,2018-01-01:/2018/exploring-4-languages-project-setup.htmlfunctional programmingrustelmfsharpreasonmldomain-driven designfour-languagesExploring 4 Languageshttp://v4.chriskrycho.com/2017/exploring-4-languages.html<p>Today, as I hit the first of the implementation chapters in <a href="https://pragprog.com/book/swdddf/domain-modeling-made-functional"><em>Domain Modeling Made Functional</em></a>, I started thinking about how I wanted to implement it. As I’ve noted <a href="https://twitter.com/chriskrycho/status/934170826718429184">elsewhere</a> in the past, very little of the book is <em>truly</em> specific to F<sup>♯</sup>, though that’s the language Wlaschin uses in the book—and Wlaschin himself <a href="https://twitter.com/ScottWlaschin/status/934177554331848705">agrees</a>:</p> <blockquote> <p>Thanks! Yes, it’s true that you could easily use #ElmLang, #RustLang, #Scala, or especially #OCaml to work through the book. I use hardly any F# specific features.</p> </blockquote> <p>So… I decided to try something a little bit bonkers. I’m going to implement these exercises in <em>four different languages</em>:</p> <ul> <li><a href="https://www.rust-lang.org">Rust</a></li> <li><a href="http://elm-lang.org">Elm</a></li> <li><a href="http://fsharp.org">F<sup>♯</sup></a></li> <li><a href="https://reasonml.github.io">ReasonML</a></li> </ul> <p>These languages are all related: they’re descended from <a href="http://smlnj.org/sml.html">Standard ML</a>. ReasonML and F<sup>♯</sup> are like siblings: Reason is merely a custom syntax for OCaml; F<sup>♯</sup> is (originally) an implementation of OCaml on .NET (though the two languages have diverged since F<sup>♯</sup> came into existence). Elm and Rust are cousins of each other and of Reason and F<sup>♯</sup>, though they’re both drawing on other languages besides OCaml as well. I also have some familiarity with Rust, Elm, and F<sup>♯</sup> already, and have read the docs for Reason a couple times. So this is a <em>bit</em> less crazy than it might otherwise be.</p> <p>Why, though? Mostly because I think it’ll be interesting to compare the implementations of the domain model from the book side by side. It’ll look just a bit different in each language, and I expect to learn a bit more of the <em>feel</em> of each language by doing this. (That side by side comparison is something I’ve <a href="http://v4.chriskrycho.com/rust-and-swift.html" title="Series: Rust and Swift">done before</a> and <a href="http://v4.chriskrycho.com/2015/rust-and-swift-v.html" title="Part V: The value (and challenge) of learning languages in parallel.">found very profitable</a>.) I’ll also turn it into blog posts, which hopefully will be interesting to others!</p> <p>More to come, and soon.</p> Chris KrychoSun, 31 Dec 2017 20:20:00 -0500tag:v4.chriskrycho.com,2017-12-31:/2017/exploring-4-languages.htmlfunctional programmingrustelmfsharpreasonmldomain-driven designfour-languagesBecoming a Contributorhttp://v4.chriskrycho.com/2017/becoming-a-contributor.html<p><i class=editorial>Here is the full text of the talk I gave at Rust Belt Rust, as it was prepared; headings correspond to individual slides. You can see the slides as they were presented <a href="/talks/rust-belt-rust/">here</a>. Note that I extemporize fairly freely when actually giving a talk, so this is <em>not</em> a word-for-word equivalent of the talk as delivered, but the gist is the same!</i></p> <p><i class=editorial>I’ll update this post with the video once it’s available!</i></p> <hr /> <figure> <img src="/talks/rust-belt-rust/img/family.jpg" alt="family" /><figcaption>family</figcaption> </figure> <p>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.</p> <section id="introduction-the-big-ideas" class="level3"> <h3>Introduction: The Big Ideas</h3> <p>The first thing I hope all of you take away is that <strong>there is no reason <em>you</em> cannot contribute meaningfully</strong> 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 “<em>especially</em> you”. The fact that you’re an outsider, or new to programming, or new to systems programming: sometimes that makes you a <em>better</em> 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: <strong>you can contribute</strong>.</p> <p>The second idea I hope you take away is <strong>just <em>how many</em> ways there are to contribute meaningfully</strong>. 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 <em>shipping code</em> 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: <strong>there are an <em>astounding</em> number of ways you can contribute</strong>.</p> </section> <section id="introduction-why" class="level3"> <h3>Introduction: Why?</h3> <p>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 <em>people</em>. To borrow a label from Scott Wlaschin – a developer I admire enormously, mostly working over in the F# community – I am a <em>humanist</em>, not a <em>technologist</em>. 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:</p> </section> <section id="introduction-the-big-ideas-1" class="level3"> <h3>Introduction: The Big Ideas</h3> <p>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 <em>contributor</em>.</p> </section> <section id="introduction-outline" class="level3"> <h3>Introduction: Outline</h3> <p>We’re going to take this on in the good old grammar-school fashion: <em>who</em>, <em>what</em>, <em>when</em>, <em>where</em>, <em>why</em>, and <em>how</em>. We’re not going to take them in that order though, and we might smash a few of them together.</p> <ol type="1"> <li>Introduction</li> <li>Why bother contributing? <!-- .element: class="fragment" data-fragment-index="1" --></li> <li>Who is a contributor? <!-- .element: class="fragment" data-fragment-index="2" --></li> <li>What is a contribution? How can you contribute? <!-- .element: class="fragment" data-fragment-index="3" --> <ul> <li>…so many things they won’t fit on this slide. <!-- .element: class="fragment" data-fragment-index="4" --></li> </ul></li> <li>When and where to contribute? <!-- .element: class="fragment" data-fragment-index="5" --></li> <li>Conclusion <!-- .element: class="fragment" data-fragment-index="6" --></li> </ol> </section> <section id="why-bother-contributing" class="level2"> <h2>Why bother contributing?</h2> <p>The first question we might be asking is: <em>why contribute at all</em>? 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.</p> </section> <section id="who-is-a-contributor" class="level2"> <h2>Who is a contributor?</h2> <p>People define this differently, but I have a very simple definition: <strong>A contributor is <em>anyone</em> who improves a project.</strong></p> <section id="who-is-a-contributor-examples" class="level3"> <h3>Who is a contributor? Examples</h3> <p>For example:</p> <ul> <li>submit a patch to fix a typo <!-- .element: class="fragment" data-fragment-index="1" --></li> <li>add a small correction for a code sample in a project <!-- .element: class="fragment" data-fragment-index="2" --></li> <li>file an issue instead of just suffering through a problem in silence <!-- .element: class="fragment" data-fragment-index="3" --></li> <li>everything else we’re going to talk about today <!-- .element: class="fragment" data-fragment-index="4" --></li> </ul> </section> <section id="who-is-a-contributor-me" class="level3"> <h3>Who is a contributor? Me!</h3> <p>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 <em>keep</em> contributing.</p> <p><img src="/talks/rust-belt-rust/img/first-commit.png" alt="my first Rust commit" /><!-- .element: class="fragment" data-fragment-index="1" --></p> </section> <section id="who-is-a-contributor-1" class="level3"> <h3>Who is a contributor?</h3> <p>I don’t imagine the story is all that different for <em>most</em> 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 <em>meant</em> for. It’s part of us in a deep, deep way.</p> </section> </section> <section id="who-is-a-contributor-2" class="level2"> <h2>Who is a contributor?</h2> <p>If you’re inclined to quibble with that definition, I challenge you to ask <em>why?</em> 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.</p> <p>There’s no magic that makes you qualified to be a contributor. There’s just a willingness to serve where you see a need.</p> </section> <section id="what-how-can-you-contribute" class="level2"> <h2>What &amp; how can you contribute?</h2> <p>And that takes us into the “what” of all of this, the <em>how</em>. (Yes, I’m combining those two). <strong><em>What</em> is a contribution? <em>How</em> can you contribute?</strong> Turns out, this is a <em>long</em> list.</p> <section id="what-how-code" class="level3"> <h3>What &amp; how: code</h3> <p>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 <em>is okay</em>. The whole point of these kinds of issues is that they give you a place where you can jump in safely.</p> <p><img src="/talks/rust-belt-rust/img/good-first-issue.png" alt="good first issue" /> <img src="/talks/rust-belt-rust/img/mentored.png" alt="mentored" /> <img src="/talks/rust-belt-rust/img/easy.png" alt="easy" /></p> <p>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. <em>Lots</em> of projects in the Rust ecosystem are like this.</p> <section id="what-how-code-were-kind-here" class="level4"> <h4>What &amp; how: code – we’re kind here</h4> <p>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. <em>Everyone</em> makes mistakes!</p> <p>Instead, we <em>want</em> people to show up, knowing nothing: we’re happy to help. Remember: we want people to contribute! 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!</p> <p><img src="/talks/rust-belt-rust/img/good-first-issue.png" alt="good first issue" /> <img src="/talks/rust-belt-rust/img/mentored.png" alt="mentored" /> <img src="/talks/rust-belt-rust/img/easy.png" alt="easy" /></p> </section> <section id="what-how-code-a-caveat" class="level4"> <h4>What &amp; how: code – a caveat</h4> <p>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 <em>over</em>-value the code. That might sound crazy, given that it’s open-source <em>software</em>, but the reality is that no one fails to value the code. We <em>do</em> 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 <em>useful</em> software without a lot of other things besides the code, and we often undervalue those.</p> </section> </section> <section id="filing-bugs" class="level3"> <h3>Filing bugs</h3> <p>So let’s take one step away from code, and talk about what is probably the single <em>easiest</em> way anyone can contribute. <em>File issues.</em> 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 <em>doesn’t know there’s a problem</em>. The only way they can fix it is if they know about it!</p> <figure> <img src="/talks/rust-belt-rust/img/new-issue.png" alt="filing bugs" /><figcaption>filing bugs</figcaption> </figure> </section> <section id="docs" class="level3"> <h3>Docs</h3> <p>Perhaps the thing most of you will be most persuaded of the utility of is <em>documentation</em>. 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, <em>sucks</em>.</p> <p>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!</p> <section id="docs-who" class="level4"> <h4>Docs: who?</h4> <p>One kind of documentation is <strong>explanation of how things work under the hood</strong>. 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.</p> <p>Another kind of documentation, though, developers and maintainers are often really poorly equipped to write, and that’s <strong>introductory documentation</strong>. This is the problem of expertise: when you know exactly how something is <em>meant</em> 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 <em>can’t</em> 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.</p> </section> <section id="docs-how" class="level4"> <h4>Docs – how?</h4> <p>What that means is that one of the most valuable things you can do as you learn a new library is <em>write down the things you don’t understand from the docs as you go</em>. And when you figure them out, <em>write that down, too</em>. 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 <em>can</em> 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.</p> <ol type="1"> <li>Write down the things you don’t understand from the docs as you go.<!-- .element: class="fragment" data-fragment-index="1" --></li> <li>When you figure them out, write that down, too.<!-- .element: class="fragment" data-fragment-index="2" --></li> <li>Then: file an issue or write a PR to improve it!<!-- .element: class="fragment" data-fragment-index="3" --></li> </ol> </section> <section id="docs-varieties" class="level4"> <h4>Docs: varieties</h4> <p>So what kinds of things would we call <em>documentation</em>?</p> <ul> <li>API documentation<!-- .element class="fragment" data-fragment-index="1" --></li> <li>READMEs<!-- .element class="fragment" data-fragment-index="2" --></li> <li>Tutorials<!-- .element class="fragment" data-fragment-index="3" --></li> <li>Books<!-- .element class="fragment" data-fragment-index="4" --></li> <li>The Rust Reference<!-- .element class="fragment" data-fragment-index="5" --></li> </ul> <p>Okay, books are a <em>huge</em> 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.</p> <p>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 <em>really</em> 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.</p> </section> <section id="docs-translation" class="level4"> <h4>Docs: Translation</h4> <p>Another huge place you can contribute to documentation is <em>translation</em>. For good or ill, English has become the sort of <em>primary</em> language of programming, but that doesn’t mean we should treat it as the <em>only</em> language, or as <em>more important</em> 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.</p> <figure> <img src="/talks/rust-belt-rust/img/translation.png" alt="translation" /><figcaption>translation</figcaption> </figure> <p>But many of you out there <em>are</em> multilingual, and could take docs written in English and convert them for, say, Czech-speaking developers. Perhaps just as importantly, you can go the <em>other</em> 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: <em>use</em> the fact that English <em>is</em> the common language to increase the reach of non-Western developers!</p> </section> </section> <section id="visual-design" class="level3"> <h3>Visual Design</h3> <p>One of the areas where you could move the ball down the field fastest in the Rust community is with <strong><em>visual</em> design</strong>. (To be clear, the <em>language</em> design is great!) But our websites could sometimes use some work.</p> <section id="visual-design-its-not-just-us" class="level4"> <h4>Visual design: it’s not just us</h4> <p>Systems programming language types have historically <em>not</em> spent a lot of time on the <em>presentation</em> 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 <em>likelier</em> 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 <em>does</em> matter, and it matters especially as we want to enable more and more people to be able to write this kind of code.</p> <p>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 <em>bad</em> way: no CSS, no attention to organization of the material, no structure to help you find your way through it.</p> </section> <section id="visual-design-how" class="level4"> <h4>Visual design: how</h4> <p>If you’re an expert or just a talented amateur, please pitch in<!-- .element: class="fragment" data-fragment-index="1" --></p> <p>You can help here even if you’re not especially comfortable with visual design or even if you’re outright bad at it 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 use one of these simple starter kits:</p> <ul> <li><a href="http://usewing.ml">Wing</a></li> <li><a href="https://purecss.io">Pure.css</a></li> <li><a href="http://getskeleton.coma">Skeleton</a></li> </ul> <p>So don’t think that just because you aren’t a design expert means you can’t help here.</p> <p>Just as important as the <em>visual</em> design is thinking about and actively designing the <strong>information hierarchy</strong> 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 <em>outline</em>. 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 <em>structure</em> and <em>organization</em> of their content, that can make an enormous differences as well.</p> </section> </section> <section id="blogging" class="level3"> <h3>Blogging</h3> <p>One of the other big ways you can help a project may not even end up in the repository at all. You can <em>blog</em>.</p> <p>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.</p> <section id="blogging-easy-mode" class="level4"> <h4>Blogging: “Easy Mode”</h4> <p>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 <em>superb</em> example of this which is <em>very</em> 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.</p> <blockquote> <p>Just write down what you’re learning.<br/> —Me, just now</p> </blockquote> </section> <section id="blogging-good-examples" class="level4"> <h4>Blogging: good examples</h4> <p>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 <em>content</em> (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.</p> </section> <section id="blogging-all-the-options" class="level4"> <h4>Blogging: all the options!</h4> <p>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.</p> <p>But blog posts can also be much more versatile than traditional documentation.</p> <ul> <li><strong>They can be one-offs, or series.</strong> You can give a topic as much depth, or as little depth, as you <em>care about</em> or <em>think it deserves</em>. 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 <em>documentation</em>, but there’s a lot people can learn from those kinds of things.</li> <li><strong>They can introduce a technology, or dig deep into how to use it, or how it’s built.</strong> 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.</li> <li><strong>They can critique or highlight problems with specific pieces of the ecosystem!</strong> 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 <em>lot</em> 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 <em>incredibly</em> valuable. Because we all have blind spots, and someone else’s perspective can help jar us out of those.</li> <li><strong>They can show how to <em>integrate</em> different parts of the ecosystem.</strong> 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 <em>huge</em>! 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 <em>having built something</em> in a relatively small amount of time. That’s also helpful because (almost) no one is building something with <em>just</em> Diesel, or just <em>any</em> crate. A huge part of what every software developer does is about fitting together other pieces of software.</li> <li><strong>They can invite feedback on your own projects.</strong> 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!</li> </ul> <p>And that’s just scratching the surface. Blogs are incredibly versatile, and you should lean on that.</p> </section> </section> <section id="audio-and-video" class="level3"> <h3>Audio and Video</h3> <p>Not just words! Noises and pictures, too!</p> <section id="audio-podcasts" class="level4"> <h4>Audio: podcasts</h4> <ul> <li>Not everyone learns the same way.<!-- .element: class="fragment" data-fragment-index="1" --></li> <li>Lots of people have commutes.<!-- .element: class="fragment" data-fragment-index="2" --></li> </ul> </section> <section id="audio-but-there-are-already-podcasts" class="level4"> <h4>Audio: but there are already podcasts</h4> <p>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 <em>huge</em> need for more audio and video content in this space!</p> <p>One podcast is not enough!</p> <figure> <img src="/talks/rust-belt-rust/img/newrustacean.png" alt="New Rustacean" /><figcaption>New Rustacean</figcaption> </figure> <p><em>Two</em> podcasts is not enough!</p> <figure> <img src="/talks/rust-belt-rust/img/rfe.png" alt="Request for Explanation" /><figcaption>Request for Explanation</figcaption> </figure> <p>Seriously, not even <em>three</em> podcasts is enough!</p> <figure> <img src="/talks/rust-belt-rust/img/rusty-spike.png" alt="Rusty Spike" /><figcaption>Rusty Spike</figcaption> </figure> <p>So I’m laying down another challenge: there’s plenty of room for more, and more kinds, of audio content in this ecosystem.</p> </section> <section id="video" class="level4"> <h4>Video</h4> <p>Again: people have different learning styles!</p> <p>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 <em>need</em> 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.</p> </section> <section id="video-what" class="level4"> <h4>Video: what</h4> <p>There are lots of options here—not just live streaming!</p> <p>Another, totally different tack you can take with video is <em>live-streaming</em>. 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. You can also do like I did and live-pair on something. It’s a pain to set up, but it’s also a lot of fun.</p> <p>And no doubt there are more ideas you have—please just go do them!</p> </section> </section> <section id="talk-to-people" class="level3"> <h3>Talk to people</h3> <p>Just talking with people matters. And there are lots of places to do it:</p> <ul> <li>IRC/Gitter/Slack/Discourse</li> <li>Meetups</li> <li>Conferences</li> </ul> <p>You can also host or help with a local meet-up! For a lot of people, one of the major challenges of learning <em>any</em> 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 <em>go</em> 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.</p> <p>Physicality matters. Presence matters. (We know this! We’re at a conference!)</p> </section> <section id="being-inviting" class="level3"> <h3>Being inviting</h3> <p>Last but not least in this list of <em>how</em> 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:</p> <ul> <li><p>The most important thing you can do is practice <strong>welcome people.</strong> 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 <em>incredibly</em> 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.</p></li> <li><p>The second big thing you can do is <strong>mentoring.</strong> 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 <em>some</em> 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 <em>have</em> written, I was able to write because someone more comfortable with some of the infrastructure mentored <em>me</em> through its quirks and oddities.</p></li> </ul> </section> </section> <section id="when-where-to-contribute" class="level2"> <h2>When &amp; where to contribute</h2> <p>The last thing I want to touch on is <em>when and where</em> to contribute. There are two things I’d suggest you should consider here:</p> <section id="when-where-you" class="level3"> <h3>When &amp; where: you</h3> <p>Where are <em>you</em> in the process of becoming comfortable with contributing?</p> <ul> <li>Just getting started?<!-- .element: class="fragment" data-fragment-index="1" --></li> <li>Already comfortable?<!-- .element: class="fragment" data-fragment-index="2" --></li> </ul> <p>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 <em>this</em> ecosystem.</p> <section id="when-where-if-youre-just-getting-started" class="level4"> <h4>When &amp; where: if you’re just getting started</h4> <p>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 <em>used to</em> helping people make their first contributions. Crazy as it seems, something like Servo can actually be an <em>easier</em> 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.</p> <ol type="1"> <li><p>Look for these!<!-- .element: class="fragment" data-fragment-index="1" --></p> <p class="fragment" data-fragment-index="1"> <p><img src="/talks/rust-belt-rust/img/help-wanted.png" alt="help wanted" /> <img src="/talks/rust-belt-rust/img/easy.png" alt="help wanted" /></p> </p></li> <li><p>Pick big projects!<!-- .element: class="fragment" data-fragment-index="2" --></p></li> </ol> </section> <section id="when-where-if-youre-experienced" class="level4"> <h4>When &amp; where: if you’re experienced</h4> <p>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 <em>could use the help</em>. Because again, there’s always more work to do than hands to do it.</p> </section> <section id="when-where-project-lifecycles" class="level4"> <h4>When &amp; where: project lifecycles</h4> <p>The second consideration dovetails nicely with that: <strong>where is a given project at in its life-cycle?</strong> 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 <em>if</em> 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 <em>also</em> usually have huge needs in terms of all those non-code avenues we talked about).</p> <p>Where is a given project at in its life-cycle?</p> <ul> <li>small project, basically done?<!-- .element: class="fragment" data-fragment-index="1" --></li> <li>need docs?<!-- .element: class="fragment" data-fragment-index="1" --></li> <li>big project, a billion needs?<!-- .element: class="fragment" data-fragment-index="1" --></li> <li>etc.<!-- .element: class="fragment" data-fragment-index="1" --></li> </ul> <p>Think about 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!</p> </section> </section> </section> <section id="conclusion" class="level2"> <h2>Conclusion</h2> <p>And that’s a good place to wrap things up! I hope you’re feeling like <em>you can do this</em>. 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! And remember:</p> <ul> <li>Anyone can contribute meaningfully.</li> <li>People can contribute in a stunning variety of ways.</li> </ul> </section> <section id="more-info" class="level2"> <h2>More info</h2> <ul> <li><a href="https://www.rust-lang.org/en-US/contribute.html" class="uri">https://www.rust-lang.org/en-US/contribute.html</a></li> <li><a href="https://blog.rust-lang.org/2017/09/18-impl-future-for-rust.html" class="uri">https://blog.rust-lang.org/2017/09/18-impl-future-for-rust.html</a></li> <li><a href="https://internals.rust-lang.org/" class="uri">https://internals.rust-lang.org/</a></li> <li><code>#rust</code>, <code>#rust-community</code>, <code>#rust-internals</code>, etc. on irc.mozilla.org</li> </ul> </section> Chris KrychoThu, 02 Nov 2017 07:00:00 -0400tag:v4.chriskrycho.com,2017-11-02:/2017/becoming-a-contributor.htmltalkssoftware developmentrustopen source softwareBetter Off Using Exceptions?http://v4.chriskrycho.com/2017/better-off-using-exceptions.html<p>I saw this post on error-handling in F<sup>♯</sup>, <a href="https://eiriktsarpalis.wordpress.com/2017/02/19/youre-better-off-using-exceptions/" title="You’re better off using Exceptions">“You’re better off using Exceptions”</a> making the rounds on Twitter:</p> <blockquote> <p>Exception handling is an error management paradigm that has often been met with criticism. Such criticisms typically revolve around scoping considerations, exceptions-as-control-flow abuse or even the assertion that exceptions are really just a type safe version of goto. To an extent, these seem like valid concerns but it is not within the scope of this article to address those per se.</p> <p>Such concerns resonate particularly well within FP communities, often taken to the extreme: we should reject exceptions Show more…</p> </blockquote> <p>And I get the argument, and in the specific context of F<sup>♯</sup>—especially given how much C<sup>♯</sup>-interoperating and therefore exception-throwing-code-interoperating there is there—it’s reasonable.</p> <p>But it still makes me sad. (To be clear: exceptions were and are a big win over what you get in languages like C. I’ll take them any day over <code>goto</code> or <code>segfault</code>.)</p> <p>You need to embrace exceptions in F<sup>♯</sup> <em>because F<sup>♯</sup> has exceptions</em> and because <em>many of its libraries rely on exceptions</em>. But my experience with Rust and other non-exception-using languages is that you <em>don’t</em> need exceptions in the general case.</p> <p>The questions are: whether your language has good support for things like flat-mapping, and whether you’re willing to commit to letting the compiler help you with these problems.</p> <p>To be sure: there’s more work involved up front to deal with that. But that’s a tradeoff I’m <em>always</em> willing to make. I’d rather have the compiler tell me if I’m failing to account for something than learn because I saw a runtime error report come up in <a href="https://raygun.com">Raygun</a>, especially because that tends to mean an error that affects the user in some way.</p> <p>Rust’s model gives you something like exceptions for truly unrecoverable errors, “panics.” A panic gives you all the context you’d get from an exception (one of the virtues of exceptions highlighted in that post), but you can only “catch” it at thread boundaries, and it otherwise just kills the program. Because it’s catastrophic, you only use it where you don’t have any way to recover in your immediate context. But where you can recover in your immediate context… using something like a highly descriptive enum (just as suggested at the end of <a href="https://eiriktsarpalis.wordpress.com/2017/02/19/youre-better-off-using-exceptions/" title="You’re better off using Exceptions">that original post</a>!) is a better option.</p> <p>It’s well-understood in my circles that you shouldn’t use exceptions for things you can recover from; you should use them for things you <em>can’t</em> recover from. But in most languages which lean heavily on exceptions, you inevitably start using them for control flow. I say: if you can recover from an error… just recover from it! Account for recoverable errors as possible conditions in your program and carry on! If you can’t recover… don’t. Die and let some other part of your system kick things back off.</p> <p>In summary: yes, if you’re in F<sup>♯</sup>, use exceptions. It <em>is</em> the right thing to do in many cases (and you don’t have a choice in many others). But I’m hopeful for a future where we handle recoverable errors locally, and <a href="http://elixir-lang.org/getting-started/mix-otp/supervisor-and-application.html">act like Erlang or Elixir otherwise</a>.</p> Chris KrychoMon, 20 Feb 2017 12:00:00 -0500tag:v4.chriskrycho.com,2017-02-20:/2017/better-off-using-exceptions.htmlfsharpsoftware developmentrustfunctional programmingThe Itchhttp://v4.chriskrycho.com/2016/the-itch.html<p>It took me until just a few weeks ago to put my finger on why typed functional programming, as a style and approach, has appealed to me so much as I started picking it up over the last year. For all its novelty, typed FP feels—over and over again—<em>familiar</em>. Strange to say, but it’s true.</p> <p>This came home to me again when reading a <a href="https://medium.com/@dtinth/what-is-a-functor-dcf510b098b6#.e887yz63p">short post on functors</a>—i.e., <em>mappable</em> types. I’ve written a lot of JavaScript in the last few years, and it has been a source of constant frustration to me that <code>Array</code> implements the <code>map</code> method, but <code>Object</code> does not. Countless times, I have wanted to take an object shaped like <code>{ count: &lt;number&gt; }</code> and transform that <code>count</code>. I’m not alone in that. There’s a reason that libraries like <a href="http://underscorejs.org">Underscore</a>, <a href="https://lodash.com">Lodash</a>, and <a href="http://ramdajs.com">Ramda</a> all supply utilities to allow you to map over objects. There are also good reasons why it <em>isn’t</em> implemented for on <code>Object.prototype</code>: the reality is that coming up with a predictable <em>and</em> useful API for <em>all</em> <code>Object</code> instances is difficult at best: Objects are used for everything from dictionaries to records and strange combinations of the two. But still: there’s something there.</p> <p>And reading this post on functors, it struck me what that “something” is: object types are, in principle, functors. Maybe it doesn’t make sense to have a single <code>map</code> implementation for every <code>Object</code> instance out there. But they’re perfectly mappable. I didn’t have a word for this before tonight, but now I do. Over and over again, this is my experience with functional programming.</p> <p>There’s this familiar feeling of frustration I’m slowly coming to recognize—a mental sensation which is a little like the intellectual equivalent of an itch in a spot you can’t quite reach. You’re reaching for an abstraction to express an idea, but you don’t even know that there <em>is</em> an abstraction for it. You want to map over objects, and you don’t know why that seems so reasonable, but it does. And then someone explains functors to you. It scratches the itch.</p> <p>Another example. Since I started programming eight and a half years ago, I’ve worked seriously with Fortran, C, C++ PHP, Python, and JavaScript. In each of those languages (and especially in the C-descended languages), I have found myself reaching for enums or things like them as a way of trying to represent types and states in my system in a more comprehensive way. I figured out that you should <a href="http://wiki.c2.com/?UseEnumsNotBooleans">use enums not booleans</a> a long time before I found the advice on the internet. I was encoding error types as enum values instead of just using <code>int</code>s almost as soon as I started, because it was obvious to me that <code>ErrorCode someFunction() { ... }</code> was far more meaningful than <code>int someFunction() { ... }</code> (even if the context of C meant that the latter often implied the former, and even if it was trivial to coerce one to the other).</p> <p>Then I read <a href="https://gumroad.com/l/maybe-haskell/"><em>Maybe Haskell</em></a>, a book I’ve mentioned often on this blog because it was so revelatory for me. This is what I had been reaching for all those years—and then some. Handing data around with the constraints? Yes, please! I had played with unions, enums, structs with enums inside them, anything to try to get some type-level clarity and guarantees about what my code was doing. Haskell showed me the way; and since then Rust and Elm and F# have reinforced it many times over. <a href="https://guide.elm-lang.org/types/union_types.html">Tagged unions</a> are a joy. They let me say what I mean—finally.</p> <p>I can still feel that itch. It’s shifted a little, but it’s still there: reaching for higher abstractions to let me tell the machine more clearly what I intend. Half a dozen times this year, I’ve realized: <em>Here</em> is where dependent types would be useful. They’re far beyond me, but close enough now I can see. I’m sure a year from now, I’ll have find some tools to scratch <em>these</em> itches, only to discover a few more.</p> Chris KrychoMon, 19 Dec 2016 21:45:00 -0500tag:v4.chriskrycho.com,2016-12-19:/2016/the-itch.htmlsoftware developmentfunctional programmingRustJavaScriptRust development using VS Code on OS X, debugging includedhttp://v4.chriskrycho.com/2016/rust-development-using-vs-code-on-os-x-debugging-included.html<p><a href="https://medium.com/@royalstream/rust-development-using-vs-code-on-os-x-debugging-included-bc10c9863777#.wgjbgie5a">Super handy guide for getting a debugging/IDE environment set up for Rust.</a></p> Chris KrychoFri, 18 Nov 2016 20:48:00 -0500tag:v4.chriskrycho.com,2016-11-18:/2016/rust-development-using-vs-code-on-os-x-debugging-included.htmlsoftware developmentrustlinksUsing Rust for ‘Scripting’http://v4.chriskrycho.com/2016/using-rust-for-scripting.html<p><i class=editorial><strong>Edit</strong>: fixed some typos, cleaned up implementation a bit based on feedback around the internet.</i></p> <p><i class=editorial>A lightly edited version of this post was syndicated in <a href="https://hackerbits.com/chris-krycho-using-rust-for-scripting/">Hacker Bits, Issue 13</a>.</i></p> <hr /> <section id="i.-using-rust-instead-of-python" class="level2"> <h2>I. Using Rust Instead of Python</h2> <p>A friend asked me today about writing a little script to do a simple conversion of the names of some files in a nested set of directories. Everything with one file extension needed to get another file extension. After asking if it was the kind of thing where he had time to and/or wanted to learn how to do it himself (always important when someone has expressed that interest more generally), I said, “Why don’t I do this in Rust?”</p> <p>Now, given the description, you might think, <i class=thought>Wouldn’t it make more sense to do that in Python or Perl or even just a shell script?</i> And the answer would be: it depends—on what the target operating system is, for example, and what the person’s current setup is. I knew, for example, that my friend is running Windows, which means he doesn’t have Python or Perl installed. I’m not a huge fan of either batch scripts or PowerShell (and I don’t know either of them all that well, either).</p> <p>I could have asked him to install Python. But, on reflection, I thought: <i class=thought>Why would I do that? I can write this in Rust.</i></p> <p>Writing it in Rust means I can compile it and hand it to him, and he can run it. And that’s it. As wonderful as they are, the fact that languages like Python, Perl, Ruby, JavaScript, etc. require having the runtime bundled up with them makes just shipping a tool a lot harder—<em>especially</em> on systems which aren’t a Unix derivative and don’t have them installed by default. (Yes, I know that <em>mostly</em> means Windows, but it doesn’t <em>solely</em> mean Windows. And, more importantly: the vast majority of the desktop-type computers in the world <em>still run Windows</em>. So that’s a big reason all by itself.)</p> <p>So there’s the justification for shipping a compiled binary. Why Rust specifically? Well, because I’m a fanboy. (But I’m a fanboy because Rust often gives you roughly the feel of using a high-level language like Python, but lets you ship standalone binaries. The same is true of a variety of other languages, too, like Haskell; but Rust is the one I know and like right now.)</p> <p><i class=editorial><strong>Edit the second:</strong> this is getting a lot of views from Hacker News, and it’s worth note: I’m not actually advocating that everyone stop using shell scripts for this kind of thing. I’m simply noting that it’s <em>possible</em> (and sometimes even <em>nice</em>) to be able to do this kind of thing in Rust, cross-compile it, and just ship it. And hey, types are nice when you’re trying to do more sophisticated things than I’m doing here! Also, for those worried about running untrusted binaries: I handed my friend the code, and would happily teach him how to build it.</i></p> </section> <section id="ii.-building-a-simple-script" class="level2"> <h2>II. Building a Simple “Script”</h2> <p>Building a “script”-style tool in Rust is pretty easy, gladly. I’ll walk through exactly what I did to create this “script”-like tool for my friend. My goal here was to rename every file in a directory from <code>*.cha</code> to <code>*.txt</code>.</p> <ol type="1"> <li><p><a href="https://www.rust-lang.org/en-US/downloads.html">Install Rust.</a></p></li> <li><p>Create a new binary:</p> <pre class="sh"><code>cargo new --bin rename-it</code></pre></li> <li><p>Add the dependencies to the Cargo.toml file. I used the <a href="https://doc.rust-lang.org/glob/glob/index.html">glob</a> crate for finding all the <code>.cha</code> files and the <a href="https://clap.rs">clap</a> crate for argument parsing.</p> <pre class="toml"><code>[package] name = &quot;rename-it&quot; version = &quot;0.1.0&quot; authors = [&quot;Chris Krycho &lt;[email protected]&gt;&quot;] [dependencies] clap = &quot;2.15.0&quot; glob = &quot;0.2&quot;</code></pre></li> <li><p>Add the actual implementation to the <code>main.rs</code> file (iterating till you get it the way you want, of course).</p> <pre class="rust"><code>extern crate clap; extern crate glob; use glob::glob; use std::fs; use clap::{Arg, App, AppSettings}; fn main() { let path_arg_name = &quot;path&quot;; let args = App::new(&quot;cha-to-txt&quot;) .about(&quot;Rename .cha to .txt&quot;) .setting(AppSettings::ArgRequiredElseHelp) .arg(Arg::with_name(path_arg_name) .help(&quot;path to the top directory with .cha files&quot;)) .get_matches(); let path = args.value_of(path_arg_name) .expect(&quot;You didn&#39;t supply a path&quot;); let search = String::from(path) + &quot;/**/*.cha&quot;; let paths = glob(&amp;search) .expect(&quot;Could not find paths in glob&quot;) .map(|p| p.expect(&quot;Bad individual path in glob&quot;)); for path in paths { match fs::rename(&amp;path, &amp;path.with_extension(&quot;txt&quot;)) { Ok(_) =&gt; (), Err(reason) =&gt; panic!(&quot;{}&quot;, reason), }; } }</code></pre></li> <li><p>Compile it.</p> <pre class="sh"><code>cargo build --release</code></pre></li> <li><p>Copy the executable to hand to a friend.</p></li> </ol> <p>In my case, I actually added in the step of <em>recompiling</em> it on Windows after doing all the development on macOS. This is one of the real pieces of magic with Rust: you can <em>easily</em> write cross-platform code. The combination of Cargo and native-compiled-code makes it super easy to write this kind of thing—and, honestly, easier to do so in a cross-platform way than it would be with a traditional scripting language.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p> <p>But what’s really delightful is that we can do better. I don’t even need to install Rust on Windows to compile a Rust binary for Windows.</p> </section> <section id="iii.-cross-compiling-to-windows-from-macos" class="level2"> <h2>III. Cross-Compiling to Windows from macOS</h2> <p>Once again, let’s do this step by step. Three notes: First, I got pretty much everything other than the first and last steps here from WindowsBunny on the <a href="https://botbot.me/mozilla/rust/">#rust</a> <abbr>IRC</abbr> channel. (If you’ve never hopped into #rust, you should: it’s amazing.) Second, you’ll need a Windows installation to make this work, as you’ll need some libraries. (That’s a pain, but it’s a one-time pain.) Third, this is the setup for doing in on macOS Sierra; steps may look a little different on an earlier version of macOS or on Linux.</p> <ol type="1"> <li><p>Install the Windows compilation target with <code>rustup</code>.</p> <pre class="sh"><code>rustup target add x86_64-pc-windows-msvc</code></pre></li> <li><p>Install the required linker (<a href="http://lld.llvm.org"><code>lld</code></a>) by way of installing the LLVM toolchain.</p> <pre class="sh"><code>brew install llvm</code></pre></li> <li><p>Create a symlink somewhere on your <code>PATH</code> to the newly installed linker, specifically with the name <code>link.exe</code>. I have <code>~/bin</code> on my <code>PATH</code> for just this kind of thing, so I can do that like so:</p> <pre class="sh"><code>ln -s /usr/local/opt/llvm/bin/lld-link ~/bin/link.exe</code></pre> <p>(We have to do this because the Rust compiler <a href="https://github.com/rust-lang/rust/blob/master/src/librustc_trans/back/msvc/mod.rs#L300">specifically goes looking for <code>link.exe</code> on non-Windows targets</a>.)</p></li> <li><p>Copy the target files for the Windows build to link against. Those are in these directories, where <code>&lt;something&gt;</code> will be a number like <code>10586.0</code> or similar (you should pick the highest one if there is more than one):</p> <ul> <li><code>C:\Program Files\Windows Kits\10\Lib\10.0.&lt;something&gt;\ucrt\x64</code></li> <li><code>C:\Program Files\Windows Kits\10\Lib\10.0.&lt;something&gt;\um\x64</code></li> <li><code>C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib\amd64</code></li> </ul> <p>Note that if you don’t already have <abbr>MSVC</abbr> installed, you’ll need to install it. If you don’t have Visual Studio installed on a Windows machine <em>at all</em>, you can do that by using the links <a href="http://landinghub.visualstudio.com/visual-cpp-build-tools">here</a>. Otherwise, on Windows, go to <strong>Add/Remove Programs</strong> and opting to Modify the Visual Studio installation. There, you can choose to add the C++ tools to the installation.</p> <p>Note also that if you’re building for 32-bit Windows you’ll want to grab <em>those</em> libraries instead of the 64-bit libraries.</p></li> <li><p>Set the <code>LIB</code> environment variable to include those paths and build the program. Let’s say you put them in something like <code>/Users/chris/lib/windows</code> (which is where I put mine). Your Cargo invocation will look like this:</p> <pre class="sh"><code>env LIB=&quot;/Users/chris/lib/windows/ucrt/x64/;/Users/chris/lib/windows/um/x64/;/Users/chris/lib/windows/VC_lib/amd64/&quot; \ cargo build --release --target=x86_64-pc-windows-msvc</code></pre> <p>Note that the final <code>/</code> on each path and the enclosing quotation marks are all important!</p></li> <li><p>Copy the binary to hand to a friend, without ever having had to leave your Mac.</p></li> </ol> <p>To be sure, there was a little extra work involved in getting cross-compilation set up. (This is the kind of thing I’d love to see further automated with <code>rustup</code> in 2017!) But what we have at the end is pretty magical. Now we can just compile cross-platform code and hand it to our friends.</p> <p>Given that, I expect not to be using Python for these kinds of tools much going forward.</p> </section> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>Again: you can do similar with Haskell or OCaml or a number of other languages. And those are great options; they are in <em>some</em> ways easier than Rust—but Cargo is really magical for this.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoMon, 14 Nov 2016 22:00:00 -0500tag:v4.chriskrycho.com,2016-11-14:/2016/using-rust-for-scripting.htmlrustsoftware developmentprogramming languagesRust vs. React Native—What?http://v4.chriskrycho.com/2016/rust-vs-react-native-what.html<p><i class=editorial>I was recently discussing some thoughts I’ve had on building a top-notch application experience in a Slack team I belong to, and noted that I believe that a Rust core with native UIs is a <em>massively</em> winning strategy. A friend in the group responded that he thinks “React + JS is eating the world right now” and that “Rust as awesome for if you want to write a JS vm, or something like that… or a compiler… anything involving lots of speed and stability.” What follows is my response, lightly edited to remove details specific to that friend and to add a few further thoughts.</i></p> <hr /> <blockquote> <p>Here’s the thing: I don’t <em>care</em> what’s eating the world today, for three reasons:</p> <ol type="1"> <li>I just want to build the best stuff I can build, and native UIs are still massively better than React and even React Native<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> in innumerable ways. There are clear advantages to React Native + JavaScript, and times when you absolutely should take that approach. But there are also a lot of times and reasons why you shouldn’t. Heck, even if you just want killer performance <em>in browsers</em>, our future includes things like Rust-to-WebAssembly, and that’s a good thing.</li> <li>What was eating the world five years ago? Ten? Is it still eating the world today? I don’t feel obliged to follow those trends (not least because, not being a consultancy, following those trends doesn’t buy me anything for the things I want to do; your tradeoffs and mine look way different).</li> <li>I’m actually getting really tired of just treating as acceptable or normative the performance characteristics of browsers. Browsers are awesome. But we can (and should) do a <em>lot</em> better in terms of user experience, and I don’t see browsers catching up to what you can do with e.g. Cocoa (Touch). Sure, that doesn’t matter that much for building yet-another-storefront. (Again, there are different tradeoffs for every single app!) But why in the world are we in a spot now where one of the most popular text editors in the world is <em>slower</em> than any text editor of five years ago? That’s not a <em>necessary</em> decision, and you can (and should) go after the same degree of ease-of-extensibility that Atom has had—perhaps even using things like HTML and CSS for skinning!—while not tying yourself to the browser and its upsides and downsides for <em>everything</em>. We have <em>incredibly</em> powerful machines, and the user experience is often getting <em>slower</em>. I’m looking for ways to change that.</li> </ol> <p>Again, JS+React<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> may be <em>exactly</em> the right tradeoff for a lot of apps, and given what consultancies (like my friends’s!) are doing, I think doing that with ReactNative for apps is a <em>very</em> good move. It makes good sense business-wise, and it makes good sense in terms of the apps you’re likely to be delivering. Don’t hear me for a second saying Rust is the best for <em>everything</em>. I think it, or something like it, is a very good choice for <em>many</em> things, though, and it shouldn’t be dismissed simply because it’s a very different world from doing Ruby or Elixir or JavaScript.</p> </blockquote> <hr /> <p><i class=editorial>So much for my initial response. On reflection, I wanted to expand it a bit. So here’s another few hundred words!</i></p> <p>Beyond this, I think there’s a bit of a false dichotomy here: the idea that “lots of speed and stability” <em>aren’t</em> values we should be seeking more aggressively for <em>all</em> our apps. Fully granted that not every app needs the same <em>degree</em> of each of those, and moreover that there are a lot of ways to get to those goals. Still: speed and stability are <em>core</em> user experience values. I don’t really care how you get at those goals, whether it’s with Rust, or Elixir or Clojure, or, yes, React with TypeScript or <a href="https://flowtype.org">Flow</a>. I <em>do</em> think that Rust is, for the moment at least, uniquely positioned to add real value in this space because it gives screaming performance but with so many niceties we’re used to when writing languages like Python or Ruby and so much of the power you get in languages like OCaml or F♯.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> But at the end of the day, I think <em>all</em> apps should focus much more on speed and stability than they do today. We have supercomputers in our pockets, and we’re often shipping apps that are slower and more finicky.</p> <p>But I have this dream of a world where apps aren’t needlessly power-hungry or memory-intensive, where every swipe and or click or scroll results in buttery-smooth responses. We won’t get there by saying, “You know, Facebook is doing <em>x</em> so that’s good enough for me.”</p> <p>Of course every developer, and any given product shop or consultancy, is going to have to make decisions about which stacks it invests in. If you’re primarily shipping web applications, investing in Elixir and React with React Native for your apps is a very sensible move. Most of your clients’ native apps may not <em>need</em> the degree of polished performance you might get from writing their iOS app in Swift and their Android app in Kotlin and the core in Rust (or even C++). That tradeoff is a <em>tradeoff</em>.</p> <p>But let’s remember that there is real value there, and that some apps <em>do</em> deserve that investment. We should evaluate the tradeoffs at every turn, and our core considerations should enduringly include <em>speed and stability</em>. Don’t dismiss Rust (or Swift, or F♯) out of hand.</p> <p>Equally importantly, we need to stop assuming that just because something is eating the world today means it’s also the future. Betting big on Flash in the mid-2000s wasn’t a <em>bad</em> move by a long shot. But its massive popularity then wasn’t a good predictor for its future. That goes double, frankly, for projects coming out of Facebook or Google or similar: big companies like that have the resources to drop everything and use a new language, or a new tool, as it suits them. If you don’t believe me, look at the actual open-source records of both of those companies! What’s hot today is far more relevant to a consultancy than to a product shop. And in both cases, choosing tech suitable for the job at hand is more important yet.</p> <p>My friend gets that, for what it’s worth. He’s making the right moves for his business as the owner of a consultancy. I just want him—and lots of other people—to see where languages like Rust and Swift and F♯ might be worth considering. And speed and stability matter in a lot of places besides just compilers and VMs.</p> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>I’m aware that React-Native ultimately binds down to native widgets. It’s still not quite the same.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn2" role="doc-endnote"><p>or, frankly, Ember or whatever else; React is great, but it is also overhyped.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn3" role="doc-endnote"><p>Swift too, and honestly for a lot of things Swift is an easier experience for not <em>that</em> much less performance than Rust. But as of today you <em>can’t</em> ship core functionality in Swift for Android or Windows.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoFri, 07 Oct 2016 08:20:00 -0400tag:v4.chriskrycho.com,2016-10-07:/2016/rust-vs-react-native-what.htmlJavaScriptRustSwiftF Sharpsoftware developmentRust and Swift (xviii)http://v4.chriskrycho.com/2016/rust-and-swift-xviii.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="http://v4.chriskrycho.com/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <section id="part-i-ownership-semantics-vs.-reference-counting" class="level2"> <h2>Part I: Ownership Semantics vs. Reference Counting</h2> <p>Perhaps unsurprisingly, the Swift book follows on from its discussion of initialization with a discussion of deinitialization, and here the differences between Rust and Swift are substantial, but (as has so often been the case) so are the analogies.</p> <p>In Rust, memory is, by default, stack-allocated and -deallocated, but with a very impressive system for tracking the lifetime of that data and allowing its to be moved from one function to another. The Rust compiler tracks the <em>ownership</em> of every given item in the program as it is passed from one function to another, allowing other parts of the program to “borrow” the data safely, until a given piece of data goes out of scope entirely. At that point, Rust runs its destructors automatically. As part of its system for managing memory safely, Rust also tracks where and when a program attempts to access any given piece of data (whether directly or via reference), and will refuse to compile if you try to reference data in a place where it has already gone out of scope and been cleaned up (“dropped,” in Rust-speak).</p> <p>If this was a bit fuzzy, don’t worry: there’s a lot to say here. It’s arguably the most distinctive feature of the language, and it’s also the main thing that tends to trip up newcomers to the language. If you’re interested in further material on the topic, my own most succinct treatment of it is in <a href="http://www.newrustacean.com/show_notes/e002/index.html" title="e002: Something borrowed, something... moved?">an early episode</a> of New Rustacean, my Rust developer podcast, and <a href="https://doc.rust-lang.org/book/ownership.html">the official documentation</a> is <em>very</em> good. For now, suffice it to say: Rust does extremely rigorous <em>compile-time</em> checks to let you do C or C++-style memory management, but with absolute guarantees that you won’t have e.g. use-after-free bugs, with a default to handling everything on the stack.</p> <p>It is of course impossible to handle <em>everything</em> on the stack, so there are heap-allocated types (e.g. vectors, a dynamically sized array-like type), which are fundamentally reference (or pointer) types. But those follow the same basic rules: Rust tracks the <em>pointers</em> throughout their uses, and when they go out of scope, Rust automatically tears down not only the pointer but also the data behind it. There are times, though, when you can’t comply with Rust’s normal rules for handling multiple-access to the same data. For those situations, it also supplies some “smart pointer” container types, <code>Rc</code> and <code>Arc</code>, the <em>reference-counted</em> (non-thread-safe) and <em>atomically reference-counted</em> (thread-safe) types. Both types just wrap up a type that you intend to put on the heap with reference-counters, which increment and decrement as various pieces of a program get access to them. Note that, unlike the compiler-level, <em>compile-time</em> checks mentioned earlier, these are <em>run-time</em> counts and they therefore incur a small but real runtime performance penalty. (The distinctions between the two types have to do with how they guarantee their memory safety and what kinds of a guarantees are required for cross-thread safety, and they’re important for writing Rust but not so important for this comparison, so I’ll leave them aside.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>)</p> <p>In Swift, all class instances (which are pass-by-reference types) are tracked with <em>automatic reference counting</em> and cleaned up automatically when there are no more references to them. Don’t confuse Rust’s “<em>atomically</em> reference-counted” type with Swift’s “<em>automatically</em> reference-counted” type. Unlike Rust’s behavior in having everything checked at compile-time, reference counting is a run-time check in Swift, just as it is with the <code>Rc</code> and <code>Arc</code> types in Rust.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> But it happens for all reference types all the time in Swift, not just when specified manually as in Rust. (Value types seem to be <em>always</em> passed by value, though the compiler has some smarts about that so it doesn’t get insanely expensive.) It’s <em>automatic</em> in that the compiler and runtime handle it “behind the scenes” from the developer’s perspective.</p> <p>Swift’s approach here isn’t quite the same as having a full-on garbage-collected runtime like you’d see in Java, C<sup>#</sup>, Python, Ruby, JavaScript, etc. (and so doesn’t have the performance issues those often can). But it also isn’t like Rust’s default of having <em>no</em> runtime cost. It’s somewhere in the middle, with a goal of very good performance but good developer ergonomics. I think it achieves that latter goal: for the most part, it means that you don’t have to think about memory allocation and deallocation explicitly. Certainly there are times when you have to think about how your program handles those issues, but neither is it right up in your face like it is in Rust,<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> nor does it come with the costs of a heavier runtime (from startup, to GC pauses, to non-deterministic performance characteristics).<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></p> <p>To make it concrete, the following snippets do <em>basically</em> the same thing—but note that the reference counting is explicit in Rust. We’ll start with Rust, doing it the normal way:</p> <pre class="rust"><code>struct WouldBeJedi { name: String, rank: u8, description: String, } impl WouldBeJedi { fn new(name: &amp;str, rank: u8, description: &amp;str) -&gt; WouldBeJedi { WouldBeJedi { name: name.to_string(), rank: rank, description: description.to_string() } } } fn main() { let trainee = WouldBeJedi::new( &quot;Zayne Carrick&quot;, 1, &quot;not very competent, but still a great hero&quot;); // When calling the function, we pass it a reference, and it // &quot;borrows&quot; access to the data. But the validity of that access // is checked at compile time. `main()` keeps the &quot;ownership&quot; // of the data. describe(&amp;trainee); // When `main` ends, nothing owns the data anymore, so // Rust cleans it up. If something were still borrowing the // data (say, if we&#39;d passed a reference into another thread), // this would actually be a compile error, because references // have to be guaranteed to live as long as the thing they // point back to. Rust has tools for managing that, as well, // its &quot;lifetimes&quot;, but we can leave them aside for this example. } fn describe(trainee: &amp;WouldBeJedi) { // Rust checks at compile time to make sure there are no // mutable &quot;borrows&quot; of the data, and therefore knows // that it is safe to reference the data here, because it can // be *sure* nothing will change it at the same time. // Under the covers, this macro will actually call a // function with the data we pass it, so Rust actually checks // the ownership and borrowing state here, too. Again, all // at compile time, and therefore with no runtime penalty. println!(&quot;{} (rank {}) is {}.&quot;, trainee.name, trainee.rank, trainee.description); // When we exit the function, Rust notes that it is no // longer &quot;borrowing&quot; the data. }</code></pre> <p>And here’s the Swift code—note as well that we use a <code>class</code> not a <code>struct</code> here:</p> <pre class="swift"><code>class WouldBeJedi { let name: String let rank: UInt8 let description: String init(name: String, rank: UInt8, description: String) { self.name = name self.rank = rank self.description = description } } func main() { let aTrainee = WouldBeJedi( name: &quot;Zayne Carrick&quot;, rank: 1, description: &quot;not very competent, but a great hero&quot;) // When calling the function, the reference count goes up // here, too, but it&#39;s implicit, rather than explicit. describe(aTrainee) // The implicit reference count Swift maintains for `aTrainee` // will go from 1 to 0 here, and Swift will do its cleanup of the // object data. } func describe(_ trainee: WouldBeJedi) { // When we enter this function, Swift bumps the reference // count, from 1 to 2. Both `main` and `describe` now have a // reference to the data. // No need for the unwrapping or any of that; Swift handles it // all automatically... thus the name of the technology! print(&quot;\(trainee.name) (rank \(trainee.rank)) is \(trainee.description).&quot;) // When we exit the function, Swift bumps the reference count // back down to 1 automatically. }</code></pre> <p>Finally, here is the (much longer, because all the reference counting is done explicitly) reference-counted Rust version:</p> <pre class="rust"><code>use std::rc::Rc; pub struct WouldBeJedi { name: String, rank: u8, description: String, } fn main() { let trainee = WouldBeJedi { name: &quot;Zayne Carrick&quot;.to_string(), rank: 1, description: &quot;not very competent, but a great hero&quot;.to_string() }; let wrapped_trainee = Rc::new(trainee); // Start by calling `clone()` to get a *reference* to the // trainee. This increases the reference count by one. let ref_trainee = wrapped_trainee.clone(); // Then pass the reference to the `describe()` function. // Note that we *move* the reference to the function, so // once the function returns, the reference will go out // of scope, and the reference count will decrement. describe(ref_trainee); // When `main` ends, several things will happen in order: // 1. The reference count on the `wrapped_trainee` will // go to zero. As a result, the `wrapped_trainee` // pointer---the `Rc` type we created---will get // cleaned up. // 2. Once `wrapped_trainee` has been cleaned up, Rust // will notice that there are no more references // anywhere to `trainee` and clean it up as well. // (More on this below.) } fn describe(trainee: Rc&lt;WouldBeJedi&gt;) { // We now have a *reference* to the underlying data, and // therefore can freely access the underlying data. println!(&quot;{} (rank {}) is {}.&quot;, trainee.name, trainee.rank, trainee.description); // When we exit the function, Rust destroys this *owned* // clone of the reference, and that bumps the reference // count back down to 1 automatically. }</code></pre> <p>Note that if we strip out all the explanatory comments and details, the <em>normal</em> versions of the Rust and Swift code are pretty similar.</p> <p>Rust—</p> <pre class="rust"><code>struct WouldBeJedi { name: String, rank: u8, description: String, } impl WouldBeJedi { fn new(name: &amp;str, rank: u8, description: &amp;str) -&gt; WouldBeJedi { WouldBeJedi { name: name.to_string(), rank: rank, description: description.to_string() } } } fn main() { let trainee = WouldBeJedi::new( &quot;Zayne Carrick&quot;, 1, &quot;not very competent, but still a great hero&quot;); describe(&amp;trainee); } fn describe(trainee: &amp;WouldBeJedi) { println!(&quot;{} (rank {}) is {}.&quot;, trainee.name, trainee.rank, trainee.description); }</code></pre> <p>Swift (as usual, is <em>slightly</em> briefer than Rust)—</p> <pre class="swift"><code>class WouldBeJedi { let name: String let rank: UInt8 let description: String init(name: String, rank: UInt8, description: String) { self.name = name self.rank = rank self.description = description } } func main() { let aTrainee = WouldBeJedi( name: &quot;Zayne Carrick&quot;, rank: 1, description: &quot;not very competent, but a great hero&quot;) describe(aTrainee) } func describe(_ trainee: WouldBeJedi) { print(&quot;\(trainee.name) (rank \(trainee.rank)) is \(trainee.description).&quot;) }</code></pre> <p>Note that in both of these implementations, all the actual cleanup of the memory is handled behind the scenes—this feels much more like writing Python than writing C, <em>especially</em> for complex data types. Not least because this same kind of nice cleanup can happen for complex, heap-allocated types like dynamically-sized vectors/arrays, etc. Both languages just manage it automatically. (The same is true of modern C++, for the most part, but it has a more complicated story there because of its relationship with C, where <code>malloc</code> and <code>free</code> and friends run rampant and are quite necessary for writing a lot of kinds of code.) Most of the time, when you’re done using data, you just <em>stop using it</em>, and both Rust and Swift will clean it up for you. The feel of using either language is fairly similar, though the underlying semantics are quite different.</p> <hr /> </section> <section id="part-2-deconstructiondeinitialization" class="level2"> <h2>Part 2: Deconstruction/Deinitialization</h2> <p>Both Rust and Swift recognize that, the ordinary case notwithstanding, there are many times when you <em>do</em> need to run some cleanup as part of tearing down an object. For example, if you had an open database connection attached to an object, you should return it to the collection pool before finishing tear-down of the object.</p> <p>In Rust, this is accomplished by implementing the <code>Drop</code> trait and supplying the requisite <code>drop</code> method. Imagine we had defined a <code>Jedi</code> type, with a bunch of details about the Jedi’s lightsaber (including whether the Jedi even <em>has</em> a lightsaber. We know from the <em>Star Wars</em> movies that lightsabers turn off automatically when the Jedi dies, or even just drops it for that matter. We can implement <em>all</em> of this in Rust using just the <code>Drop</code> trait. Here’s a pretty full example.<a href="#fn5" class="footnote-ref" id="fnref5" role="doc-noteref"><sup>5</sup></a> (Note that both of these implementations draw heavily on material I covered in <a href="http://v4.chriskrycho.com/rust-and-swift.html">previous posts</a>.)</p> <pre class="rust"><code>#[derive(Debug)] enum Color { Red, Blue, Green, Purple, Yellow } enum SaberState { On, Off, } struct Lightsaber { color: Color, blades: u8, state: SaberState } impl Lightsaber { pub fn new(color: Color, blades: u8) -&gt; Lightsaber { if blades &gt; 2 { panic!(&quot;That&#39;s just silly. Looking at you, Kylo.&quot;); } Lightsaber { color: color, blades: blades, state: SaberState::Off } } pub fn on(&amp;mut self) { self.state = SaberState::On; } pub fn off(&amp;mut self) { self.state = SaberState::Off; } } struct WouldBeJedi { name: String, lightsaber: Option&lt;Lightsaber&gt;, } impl WouldBeJedi { pub fn new(name: &amp;str, lightsaber: Option&lt;Lightsaber&gt;) -&gt; WouldBeJedi { WouldBeJedi { name: name.to_string(), lightsaber: lightsaber } } pub fn describe(&amp;self) { let lightsaber = match self.lightsaber { Some(ref saber) =&gt; format!(&quot;a {:?} lightsaber with {:} blades.&quot;, saber.color, saber.blades), None =&gt; &quot;no lightsaber.&quot;.to_string() }; println!(&quot;{} has {}&quot;, self.name, lightsaber) } } // Here&#39;s the actually important bit. impl Drop for WouldBeJedi { fn drop(&amp;mut self) { if let Some(ref mut lightsaber) = self.lightsaber { lightsaber.off(); } } } fn main() { let saber = Lightsaber::new(Color::Yellow, 1); let a_jedi = WouldBeJedi::new(&quot;Zayne Carrick&quot;, Some(saber)); a_jedi.describe(); }</code></pre> <p>We can do much the same in Swift, using its deinitializers, which are fairly analogous to (but much simpler than) <a href="http://v4.chriskrycho.com/2016/rust-and-swift-xvii.html">its initializers</a>, and fulfill the same role as Rust’s <code>Drop</code> trait and <code>drop()</code> method.</p> <pre class="swift"><code>enum Color { case red, blue, green, purple, yellow } enum SaberState { case on, off } struct Lightsaber { let color: Color let blades: UInt8 var state: SaberState = .off init?(color: Color, blades: UInt8) { if blades &gt; 2 { print(&quot;That&#39;s just silly. Looking at you, Kylo.&quot;) return nil } self.color = color self.blades = blades } mutating func on() { state = .on } mutating func off() { state = .off } } class WouldBeJedi { let name: String var lightsaber: Lightsaber? init(name: String, lightsaber: Lightsaber?) { self.name = name self.lightsaber = lightsaber } deinit { self.lightsaber?.off() } func describe() { let saberDescription: String if let saber = self.lightsaber { saberDescription = &quot;a \(saber.color) lightsaber with \(saber.blades) blades.&quot; } else { saberDescription = &quot;no lightsaber.&quot; } print(&quot;\(name) has \(saberDescription)&quot;) } } func main() { let saber = Lightsaber(color: .yellow, blades: 1) let aJedi = WouldBeJedi(name: &quot;Zayne Carrick&quot;, lightsaber: saber) aJedi.describe(); }</code></pre> <p>This is a bit briefer, but that’s mostly down to Swift’s shorthand for optionals (the <code>?</code> operator), which we’ll get to in a future post.</p> <p>Curiously, <code>struct</code> and <code>enum</code> types <em>cannot</em> have deinitializers in Swift. I expect this has something to do with their being value types rather than reference types, but the book offers no comment. (If a reader knows the answer, I’d welcome clarification.)</p> <p>Much as in the discussion of of initializers, the usual patterns with Rust and Swift’s approach come into play. Rust opts to build the pattern on the same basic language machinery (traits). Swift uses a bit of syntactical sugar dedicated to the purpose. It’s undeniable that the Swift is a bit briefer.</p> <p>However, there are a couple upsides to Rust’s approach. First, it is applicable on <em>all</em> types, where Swift’s applies only to classes. Second, there is no additional syntax to remember. <code>Drop</code> is just a trait like any other, and <code>drop</code> a method like any other. Third, then, this means that you can run it explicitly elsewhere if you need to, and as a result you can define whatever kind of custom deconstruction behavior you might need. If we’d created <code>a_jedi</code> above in Rust, we could simply write <code>a_jedi.drop()</code> anywhere:</p> <pre class="rust"><code>fn prove_incompetent(a_jedi: WouldBeJedi) { // make some series of grievous mistakes which mean // you&#39;re no longer able to be a Jedi and as such, // among other things, lose your lightsaber... a_jedi.drop(); // other stuff }</code></pre> <p>Or (going a bit more abstract) we could define a <code>daring_derring_do()</code> method which called <code>drop()</code> itself:</p> <pre class="rust"><code>impl WouldBeJedi { pub fn daring_derring_do(self) { // do some other operation, like freeing slaves from // a secret colony of slavers. But if it fails... self.drop(); } }</code></pre> <p>Or, really, define <em>any</em> behavior which culminated in a <code>drop()</code> call. That’s extremely powerful, and it’s the upside that comes with its just being a trait whose behavior we have to define ourselves.</p> <p>That takes us back to one of the fundamental differences in design between the two languages. Rust goes out of its way to leave power in the hands of the user, at the cost of requiring the user to be a bit more explicit. Swift prioritizes brevity and productivity, but it gets there by taking some of the power out of the hands of the developer. Neither of these is wrong, <em>per se</em>. They’re just aiming for (and in this case, I think, fairly successfully landing in) somewhat different spots on a spectrum of tradeoffs.</p> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xvii.html"><strong>Previous:</strong> More on initializers!</a></li> </ul> </section> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>I did, however, cover them <a href="http://www.newrustacean.com/show_notes/e015/index.html" title="e015: Not dumb pointers">quite recently</a> on my podcast. Yes, this <em>is</em> another shameless plug.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn2" role="doc-endnote"><p>Mostly, anyway. I believe the Swift compiler also does some degree of static analysis similar to that done by Rust—though to a <em>much</em> lesser extent and, speaking purely descriptively, much less rigorously (it just has different goals). Swift then uses that analysis to handle things at compile time rather than via reference counts if it’s able to determine that it can do so.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn3" role="doc-endnote"><p>We could, if we so desired, get this same basic behavior in Rust. We can easily imagine a world in which every type was automatically wrapped in <code>Rc</code> or <code>Arc</code>, and in fact, I’d be very interested to see just such a language—something which was only a thin layer over Rust, keeping all its semantics but wrapping some or all non-stack-allocated types in <code>Rc</code> or <code>Arc</code> as appropriate. (Something like <a href="http://manishearth.github.io/blog/2015/09/01/designing-a-gc-in-rust/">this</a>, but done behind the scenes rather than manually opted into.) You’d incur some performance coasts, but with the benefit that you’d have an <em>extremely</em> ergonomic, practical, ML-descended language quite appropriate for slightly higher-level tasks, and without the radical shift required by switching to a lazily-evaluated, purely functional language like Haskell.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn4" role="doc-endnote"><p>Notably, those tradeoffs are often entirely worth it, and high-performance VMs have astoundingly good characteristics in many ways. The JVM, the CLR, and all the JavaScript VMs have astonishingly excellent performance at this point.<a href="#fnref4" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn5" role="doc-endnote"><p>I <em>might</em> have gotten slightly carried away in the details here. I’m just a little bit of a nerd.<a href="#fnref5" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoSun, 24 Jul 2016 15:10:00 -0400tag:v4.chriskrycho.com,2016-07-24:/2016/rust-and-swift-xviii.htmlrustswiftrust-and-swiftprogramming languagesRust and Swift (xvii)http://v4.chriskrycho.com/2016/rust-and-swift-xvii.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="http://v4.chriskrycho.com/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <p>In the <a href="http://v4.chriskrycho.com/2016/rust-and-swift-xvi.html">last part</a>, I talked through the first chunk of the Swift book’s material on initializers. But it’s a long section, and I definitely didn’t cover everything. (I also got a few bits incorrect, and thankfully got great feedback to tighten it up from Twitter, so if you read it right after I posted it, you might skim back through and find the places where I added “<strong>Edit:</strong> …”)</p> <p>Picking up from where we left on, then. Swift has a number of further initializer types, some of which map rather directly to the way initializers work in Rust, and some of which have no <em>direct</em> analog at all.</p> <p>In the first category are the memberwise initializers Swift supplies by default for <em>all</em> types. The most basic <code>init</code> method just uses the names of the members of any given <code>struct</code> or <code>class</code> type in Swift (as in the previous section, I’m going to use the types the Swift book uses for simplicity):</p> <pre class="swift"><code>struct Size { var height = 0.0, width = 0.0 } someSize = Size(height: 1.0, width: 2.0)</code></pre> <p>This actually looks almost exactly like the normal way we construct types in Rust, where the same basic pattern would look like this:</p> <pre class="rust"><code>struct Size { height: f64, width: f64, } some_size = Size { height: 1.0, width: 2.0 }</code></pre> <p>There are two big differences between the languages here. The first, and most immediately apparent, is syntactical: in this case, Rust doesn’t have a function-call syntax for creating instances, and Swift does. Swift’s syntax is similar to one of the several C++ constructor patterns, or especially to Python’s initializer calls (if we made a point to be explicit about the keyword arguments):</p> <pre class="python"><code>class Size: height = 0.0 width = 0.0 def __init__(height, width): self.height = height self.width = width someSize = Size(height=1.0, width=2.0) # unnecessarily explicit</code></pre> <p>The second, and more significant, is that the default, memberwise initializer in in Swift is only available <em>if you have not defined any other initializers</em>. This is very, <em>very</em> different from Rust, where there’s not really any such thing as a dedicated initializer—just methods. If we defined <code>Size::new</code> or <code>Size::default</code> or <code>Size::any_other_funky_initializer</code>, it wouldn’t make a whit of difference in our ability to define the type this way.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> However, and this is important: because Rust has field-level public vs. private considerations, we cannot always do memberwise initialization of any given <code>struct</code> type there, either; it is just that the reasons are different. So:<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p> <pre class="rust"><code>mod Shapes { struct Rectangle { pub height: f64, pub width: f64, area: f64, } } fn main() { // This won&#39;t work: we haven&#39;t constructed `Size::area`, and as we noted // last time, you cannot partially initialize a struct. let some_size = Shapes::Size { height: 1.0, width: 2.0 }; // But neither will this, because `area` isn&#39;t public: let some_other_size = Shapes::Size { height: 1.0, width: 2.0, area: 2.0 }; }</code></pre> <p>Swift lets you refer to <em>other</em> initializers on the same type (reinforcing that <code>init()</code> is basically a kind of method, albeit one with some special rules and some special sugar). You do that by calling <code>self.init()</code>, and—very importantly—you can only call it from within another initializer. No funky reinitializations or anything like that. The net result is that if you have a couple different variations on ways you might initialize a type, you still get the benefit of reusability; you don’t have to reimplement the same initialization function over and over again. Do whatever <em>additional</em> setup is required in any given instance, and then call a common base initializer.</p> <p>With Rust, again, we just have methods, so you <em>could</em> of course call them wherever you like. However, those methods are distinguished as being type-level or instance-level methods by their signatures, rather than by keyword. If the first argument is (some variant on) <code>self</code>, it’s an instance method, otherwise, a type-level method. This eliminates any potential confusion around the initializers:</p> <pre class="rust"><code>struct Foo { pub a: i32 } impl Foo { pub fn new(a: i32) -&gt; Foo { Foo { a: a } } pub fn bar(&amp;self) { // yes: let another_foo = Foo::new(); // no (won&#39;t even compile): // let self_foo = self.new(); } }</code></pre> <p>You can (of course!) build up a type through multiple layers of methods which are useful to compose an instance <em>together</em>. This is what the <a href="http://doc.rust-lang.org/stable/style/ownership/builders.html"><em>builder pattern</em></a> is all about. There are definitely times when you want to be able to tweak how your initialization plays out, and being able to do that without just passing in some hairy set of options in a special data type is nice.</p> <p>One other important qualification on the Swift initializers: those default, memberwise constructors you get for free? You <em>only</em> get them for free if you don’t define your own initializers. (The closest analogy to this in Rust is that you’ll have issues if you try to both <code>#[derive(Default)]</code> <em>and</em> <code>impl Default for Foo</code>, since both will give you an implementation of <code>Foo::default()</code>.) You can get around this in Swift by using an <em>extension</em>. We’ll come back to that in a future post.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> You can also get around it by supplying a parameter-less, body-less initializer in addition to any other initializers you supply, so: <code>init() {}</code>. (This, frankly, seems like a hack to me. It’s a <em>useful</em> hack, given the other constraints, but these kinds of things pile up.) Similarly, you can just reimplement member-wise initializers yourself if you have a reason to (say, if you’ve implemented any <em>others</em> and therefore the defaults no longer exist).</p> <p>Now things take a turn into Swift-only territory <a href="http://v4.chriskrycho.com/2016/rust-and-swift-xv.html">again</a> as we look at initialization in the context of inheritance. (As mentioned last time: Rust will eventually get inheritance-like behavior, but it’s coming much later, and is not going to be <em>exactly</em> like classical inheritance. Rust <em>strongly</em> favors composition over inheritance, where Swift <em>lightly</em> does but still supports the latter.)</p> <p>Swift has two kinds of initializers for class initializers. One, a <em>designated initializer</em>, is required; a designated initializer must fully initialize every property on a class, and call the superclass initializer (assuming there is one). These can be inherited, but again: they are required.</p> <p>There are also <em>convenience initializers</em>, which provide variant APIs for setting up any given class. These (by definition, given what we said a moment ago) <em>must</em> call a designated initializer along the way. These could be useful in a lot of different scenarios: setting up variants on the class (as in our temperature examples from before), doing alternate setup depending on initial conditions, etc.</p> <p>The only difference between the two syntactically is that <em>convenience</em> initializers get the <code>convenience</code> keyword in front of the <code>init</code> declaration, so:</p> <pre class="swift"><code>class Foo { var bar : Int let quux: String // designated init(_ bar: Int, _ quux: String) { self.bar = bar self.quux = quux } // A convenience method which only takes the string. convenience init(_ quux: String) { self.init(0, quux) } }</code></pre> <p>The Swift book gives a set of rules about how these delegated and convenience initializers must behave. The short version is that convenience initializers (eventually) have to call a delegated initializer from <em>their own</em> class, and designated initializers have to call a designated initializer from the <em>superclass</em>. This is an implementation detail, though: from the perspective of a <em>user</em> of the class, it doesn’t matter which initializer is called.</p> <p>The other important bit about Swift <em>class</em> initialization is that it is a two-phase process, which you might think of as “primary initialization” and “customization.” The primary initialization sets up the properties on a class <em>as defined by the class which introduced them</em>. The following sample should illustrate how it plays out:</p> <pre class="swift"><code>class Foo { let plainTruth = &quot;Doug Adams was good at what he did.&quot; let answer = 0 init() { baz = answer / 2 } } // Bar inherits from Foo class Bar: Foo { let question = &quot;What is the meaning of life, the universe, and everything?&quot; let answer = 42 init() { super.init() // calls Foo.init() } convenience init(newQuestion question: String, newAnswer answer: Int) { self.question = question self.answer = answer self.init() // calls own `init()` } }</code></pre> <p>When building a <code>Bar</code> via either the designated or convenience initializer, <code>plainTruth</code> and <code>answer</code> will be set up from <code>Foo</code>, then <code>question</code> will be set and <code>answer</code> will be reassigned in <code>Bar</code>. If the convenience initializer is used, then it will also override those new defaults with the arguments passed by the caller, before running the designated initializer, which will in turn call the superclass designated initializer. The machinery all makes good sense; I appreciate that there are no weird edge cases in the initialization <em>rules</em> here. (There <em>are</em> a bunch of special rules about which initializers get inherited; I’m just going to leave those aside at this point as they’re entirely irrelevant for a comparison between the languages. We’re already pretty far off into the weeds here.)</p> <p>Obviously, none of this remotely applies to Rust at all. Not having inheritance <em>does</em> keep these things simpler (though of course it also means there’s a tool missing from your toolbox which you might miss). And of course, the rules around <em>method resolution</em> are not totally trivial there, especially now that <a href="https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md"><code>impl</code> specialization</a> is making its way <a href="https://github.com/rust-lang/rust/issues/31844">into the language</a>. But those don’t strictly speaking, affect <em>initialization</em>.</p> <p>To account for the case that initialization can fail, Swift lets you definite <em>failable</em> initializers, written like <code>init?()</code>. Calling such an initializer produces an optional. You trigger the <code>nil</code> valued optional state by writing <code>return nil</code> at some point in the body of the initializer. Quoting from the Swift book, though, “Strictly speaking, initializers do not return a value…. Although you write <code>return nil</code> tro trigger an initialization failure, you do not use the <code>return</code> keyword to indicate initialization success.” These failable initializers get the same overall behavior and treatment as normal initializers in terms of delegating to other initializers within the same class, and inheriting them from superclasses.</p> <pre class="swift"><code>class Foo { let bar: Int init?(succeed: Bool) { if !succeed { return nil } bar = 42 } } let foo = Foo(true) print(&quot;\(foo?.bar)&quot;) // 42 let quux = Foo(false) Print(&quot;\(foo?.bar)&quot;) // nil</code></pre> <p>This is another of the places where Swift’s choice to treat initialization as a special case, not just another kind of method, ends up having some weird side effects. If <code>init</code> calls were <em>methods</em>, they would always just be <em>returning the type</em>. This is exactly what we see in Rust, of course. To be clear, there are reasons why the Swift team made that choice, and many of them we’ve already touched on incidentally; the long and short of it is that inheritance adds some wrinkles. These aren’t <em>constructors</em>, they’re <em>initializers</em>. The point, per the Swift book, is “to ensure that <code>self</code> is fully and correctly initializer by the time that initialization ends.” If you’re familiar with Python, you can think of Swift initializers as being quite analogous to <code>__init__(self)</code> methods, which similarly are responsible for <em>initialization</em> but not <em>construction</em>. When we build a type in Rust, by contrast, we’re doing something much more like calling Python <code>__new__(cls)</code> methods, which <em>do</em> construct the type.</p> <p><em><strong>Edit:</strong> interestingly, I’m <a href="https://twitter.com/austinzheng/status/749831726122217473">informed via Twitter</a> that Swift initializers can also throw errors. (Thanks, Austin!) The Swift book doesn’t mention this because it hasn’t gotten to error-handling yet (and so, neither have we).<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></em></p> <p>You can of course write failable constructors in Rust, too:</p> <pre class="rust"><code>struct Foo { bar: i64, }; impl Foo { pub fn optional_new(succeed: bool) -&gt; Option&lt;Foo&gt; { if succeed { Some(Foo { bar: 0 }) } else { None } } } let foo = Foo::optional_new(true); match foo { Some(f) =&gt; println!(&quot;{}&quot;, f.bar), None =&gt; println!(&quot;None&quot;), };</code></pre> <p>There are conditions in both languages where you’d want to do this: places where an initialization <em>can</em> fail, e.g. trying to open a file, or open a websocket, or anything where the type represents something that is not guaranteed to return a valid result. It makes sense then that in both cases, returning an <em>optional</em> value is the outcome. Of course, Rust can equally well have an initializer return a <code>Result&lt;T, E&gt;</code>:</p> <pre class="rust"><code>struct Waffles { syrup: bool, butter: bool, } impl Waffles { fn properly(all_supplies: bool) -&gt; Result&lt;Waffles, String&gt; { if all_supplies { Ok(Waffles { syrup: true, butter: true } ) } else { let msg = &quot;Who makes waffles this way???&quot;; Err(msg.to_string()) } } } let waffles = Waffles::properly(true); match waffles { Ok(_) =&gt; println!(&quot;Got some waffles, yeah!&quot;), Err(s) =&gt; println!(&quot;{:}&quot;, s), };</code></pre> <p><del>This is simply not the kind of thing you can do in Swift, as far as I can tell. The upside to Swift’s approach is that there is one, standard path. The downside is that if you have a scenario where it makes sense to return an error—i.e., to indicate <em>why</em> a class failed to initialize and not merely <em>that</em> it failed—you’re going to have to jump through many more hoops.<a href="#fn5" class="footnote-ref" id="fnref5" role="doc-noteref"><sup>5</sup></a></del> <em><strong>Edit:</strong> See above; Swift <em>can</em> do this. Moreover, the underlying semantics aren’t especially different from Rust’s. However, it does introduce <em>yet more</em> syntax, rather than just being a normal return. But we’ll talk about that in more detail when we get to error-handling.</em><a href="#fn4"><sup>4</sup></a> The downside for Rust is that there’s no shorthand; everything is explicit. The upside is the flexibility to do as makes the most sense in a given context, including defining whatever types you need and returning them as you see fit. If you need a type like <code>PartialSuccessPossible&lt;C, P, E&gt;</code> where <code>C</code> is a complete type, <code>P</code> a partial type, and <code>E</code> an error, you can do that. (I’m not saying that’s a good idea, for the record.) That in turn flows out of building even higher level language features on lower-level features and not introducing new syntax for the most part. Trade-offs!</p> <p>And with that, we’re done talking about initializers. This was a <em>huge</em> topic—but it makes sense. If you don’t nail this down carefully, you’ll be in for a world of hurt later, and that goes whether you’re designing a language or just using it to build things.</p> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xvi.html"><strong>Previous:</strong> Initialization: another area where Swift has a lot more going on than Rust.</a></li> <li>[**Next: Deinitialization: ownership semantics and automatic reference counting][18]</li> </ul> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>Also recall that in Rust, we would set the default values either by using the <code>#[derive(Default)]</code> annotation or by implementing the <code>Default</code> trait ourselves.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn2" role="doc-endnote"><p>I’m including a module because of a quirk around the public/private rules: within the same module, <code>area</code> isn’t hidden and you can actually go ahead and initialize the object.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn3" role="doc-endnote"><p>Depending on how you think about extensions, <em>either</em> Rust doesn’t have anything quite like them… <em>or</em> every type implementation is just an extension, because <code>impl</code> allows you to extend <em>any</em> data type in basically arbitrary ways (a few caveats of course). More on all of this when we get there.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn4" role="doc-endnote"><p>Here’s a preview of what that would look like, though (fair warning, there’s a lot going on here we haven’t talked about!):</p> <pre class="swift"><code>enum Setup { case succeed case error case fail } enum BarSetupError: ErrorProtocol { case argh } class Bar { let blah: Int init?(setup: Setup) throws { switch setup { case .succeed: blah = 42 case .error: throw BarSetupError.argh case .fail: return nil } } } do { let bar = try Bar(setup: .succeed) print(&quot;\(bar!.blah)&quot;) let baz = try Bar(setup: .fail) print(&quot;\(baz?.blah)&quot;) let quux = try Bar(setup: .error) print(&quot;\(quux?.blah)&quot;) } catch BarSetupError.argh { print(&quot;Oh teh noes!&quot;) }</code></pre> <p>The output from this would be <code>42</code>, <code>nil</code>, and <code>Oh teh noes!</code>.<a href="#fnref4" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn5" role="doc-endnote"><p><del>It’s conceivable this is actually possible, but nothing in <em>The Swift Programming Language</em> even hints at it, if so.</del> See above!<a href="#fnref5" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoThu, 30 Jun 2016 23:00:00 -0400tag:v4.chriskrycho.com,2016-06-30:/2016/rust-and-swift-xvii.htmlrustswiftrust-and-swiftprogramming languagesVectors and Iterator Access in Rusthttp://v4.chriskrycho.com/2016/vectors-and-iterator-access-in-rust.html<p><i class="editorial">In the midst of doing my reading and research for New Rustacean episode 15 (which will be out fairly soon after I post this), I bumped into this little tidbit. It doesn’t fit in the episode, so I thought I’d share it here.</i></p> <p>When you’re dealing with vectors in Rust, a common misstep when working with them via iterators is to <em>move</em> them when you only to <em>borrow</em> them. If you write <code>for i in x</code> where <code>x</code> is an iterator, you’ll <em>move</em> the iterator into the looping construct. Instead, you should nearly always write <code>for i in &amp;x</code> to borrow a reference to the iterator, or <code>for i in &amp;mut x</code> if you need to get a mutable reference to it.</p> Chris KrychoThu, 16 Jun 2016 20:59:00 -0400tag:v4.chriskrycho.com,2016-06-16:/2016/vectors-and-iterator-access-in-rust.htmlrustRust and Swift (xvi)http://v4.chriskrycho.com/2016/rust-and-swift-xvi.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="http://v4.chriskrycho.com/rust-and-swift.html">(See all parts in the series.)</a></i></p> <p><i class="editorial">Thanks to ubsan, aatch, and niconii on the <a href="https://client00.chat.mibbit.com/?server=irc.mozilla.org&amp;channel=%23rust">#rust-lang IRC</a> for a fascinating discussion of the current status of Rust’s initialization analysis, as well as some very interesting comments on what might be possible to do in the future. Everything actually interesting about Rust in this post comes from the conversation I had with them on the evening of March 13.</i></p> <hr /> <p>The rules various languages have around construction and destruction of objects are <em>extremely</em> important for programmer safety and ergonomics. I think it’s fair to say that both Swift and rust are actively trying to avoid some of the mistakes made in e.g. C++ which poorly affect both its safety and its ease of use for developers, albeit it in some superficially different ways. Both languages also support defining how types are destroyed, which we’ll come back to in a future discussion.</p> <p>The basic aim both Rust and Swift have in this area seems to be the same: avoid <em>partially</em> initialized objects. (You don’t want partially initialized objects. Ask Objective C developers.)</p> <p>Swift does this via its rules around <em>initializers</em>. Rust does it by requiring that all the values of a type be initialized at its creation. So, for example, the following <em>looks</em> like it should work, but it doesn’t. You can initialize the variable piecemeal, but you cannot <em>use</em> it:</p> <pre class="rust"><code>#[derive(Debug)] // to make it printable. struct Foo { pub a: i32, pub b: f64, } fn main() { // This will compile, but `foo` will be useless. let mut foo: Foo; foo.a = 14; foo.b = 42.0; // This would actually fail to compile. Surprising? A bit! // println!(&quot;{:?}&quot;, foo); // This will work, though, because it fully constructs the type. let foo2 = Foo { a: 14, b: 42.0 }; println!(&quot;{:?}&quot;, foo); }</code></pre> <p>(The reasons why this is so are fairly complicated. See the addendum at the end for a brief discussion.)</p> <p>In any case, this means that especially with more complex data types, providing standard constructor-style methods like <code>new</code> or <code>default</code> is conventional and helpful. (If the type has non-public members, it’s also strictly necessary.)</p> <p>Swift has a number of options for initializers, which correspond to things you in most cases can do in Rust, but in a very different way.</p> <p>First, Swift allows you to overload the <code>init</code> method on a type, so that you can have different constructors for different starting conditions. (This is, to my recollection, the first time any kind of overloading has come up so far in the Swift book—but that could just be my memory failing me. Certainly I haven’t referenced it in any previous discussion, though.)</p> <p>The example offered by the Swift book is illuminating for the different approaches the languages take, so we’ll run with it. Here’s a class defining a Celsius type in Swift:</p> <pre class="swift"><code>struct Celsius { let temp: Double init(fromFahrenheit f: Double) { temp = 1.8 * (f - 32.0) } init(fromKelvin k: Double) { temp = k - 273.15 } } // Create an instance each way let freezing = Celsius(temp: 0) let balmy = Celsius(fromFahrenheit: 75.0) let absoluteZero = Celsius(fromKelvin: 0.0)</code></pre> <p>Note the internal and external parameter names. This is a common idiom Swift keeps (albeit with some non-trivial modification, and with <a href="%7B%3E%3E%20TODO:%20Swift%203%20naming%20changes%20%3C%3C%7D">more to come</a>). More on this below; first, the same basic functionality in Rust:</p> <pre class="rust"><code>struct Celsius { temp: f64 } impl Celsius { fn from_fahrenheit(f: f64) -&gt; Celsius { Celsius { temp: 1.8 * (f - 32.0) } } fn from_kelvin(k: f64) -&gt; Celsius { Celsius { temp: k - 273.15 } } } // Create an instance each way let freezing = Celsius { temp: 0 }; let balmy = Celsius::from_fahrenheit(75.0); let absoluteZero = Celsius::from_kelvin(0.0);</code></pre> <p>(Note that there might be other considerations in implementing such types, like using a <code>Temperature</code> base <code>trait</code> or <code>protocol</code>, or employing type aliases, but those are for later entries!)</p> <p>You can see a point I made about Swift’s initializer syntax back in <a href="http://v4.chriskrycho.com/2016/rust-and-swift-x.html">part x</a>: the way Rust reuses normal struct methods while Swift has the special initializers. Neither is clearly the “winner” here. Rust gets to use existing language machinery, simplifying our mental model a bit by not adding more syntax. On the other hand, the addition of initializer syntax lets Swift use a fairly familiar type construction syntax even for special initializer cases, and a leaves us with a bit less noise in the constructor method. Note, though, that initializers in Swift <em>are</em> special syntax; they’re not just a special kind of method (as the absence of the <code>func</code> keyword emphasizes)—unlike Rust, where initializers really are just normal struct or instance methods.</p> <p>The Swift book notes this distinction:</p> <blockquote> <p>In its simplest form, an initializer is like an instance method with no parameters, written using the <code>init</code> keyword.</p> </blockquote> <p>The new keyword is the thing I could do without. Perhaps it’s just years of writing Python, but I really prefer it when constructors for types are just sugar and you can therefore reimplement them yourself, provide custom variations, etc. as it suits you. Introducing syntax instead of just picking a standard function to call at object instantiation means you lose that. At the same time, and in Swift’s defense, I’ve only rarely wanted or needed to use those facilities in work in Python. It’s a pragmatic decision—and it makes sense as such; it’s just not where my preference lies. The cost is a bit higher than I’d prefer relative to the gain in convenience.</p> <p>Back to the initializers and the issue of overloading: the external parameter names (the <em>first</em> parameter) is one of the main ways Swift tells apart the initializers. This is necessitated, of course, by the choice of a keyword for the initializer; Rust doesn’t have any <em>need</em> for this, and since Rust doesn’t have overloading, it also <em>can’t</em> do this. In Rust, different constructors/initializers will have different names, because they will simply be different methods.</p> <p>[<i class='editorial'><strong>Edit:</strong> I’m leaving this here for posterity, but it’s incomplete. See below.</i>] One other important thing falls out of this: the external parameter names are <em>required</em> when initializing a type in Swift. Because those parameter names are used to tell apart the constructor, this is not just necessary for the compiler. It’s also an essential element of making the item readable for humans. Imagine if this were <em>not</em> the case—look again at the <code>Celsius</code> example:</p> <pre class="swift"><code>struct Celsius { let temp: Double init(fromFahrenheit f: Double) { temp = 1.8 * (f - 32.0) } init(fromKelvin k: Double) { temp = k - 273.15 } } // Create an instance each way let freezing = Celsius(0) let balmy = Celsius(75.0) // our old fromFahrenheit example let absoluteZero = Celsius(0.0) // our old &quot;fromKelvin example</code></pre> <p>We as humans would have no idea what the constructors are supposed to do, and really at this point there would <em>necessarily</em> just be one constructor unless the later options took elements of another <em>type</em>. That would be fairly similar to how overloading works in C++, Java, or C<sup>♯</sup>, and while method overloading in those langauges is very <em>powerful</em>, it can also make it incredibly difficult to figure out exactly what method is being called. That includes when the constructor is being called. Take a look at the <em>long</em> list of <a href="https://msdn.microsoft.com/en-us/library/system.datetime(v=vs.110)">C<sup>♯</sup> <code>DateTime</code> constructors</a>, for example: you have to either have this memorized, have the documentation open, or be able simply to infer from context what is going on.</p> <p><em>Given</em> the choice of a keyword to mark initializers, then, Swift’s rule about external parameter name usage wherever there is more than one initializer is quite sensible.</p> <p>[<i class='editorial'><strong>Edit:</strong> several readers, most notably including <a href="https://twitter.com/jckarter/status/740763363626586112">Joe Groff</a>, who works on Swift for Apple, pointed out that Swift <em>does</em> support overloading, including in <code>init()</code> calls, and uses types to distinguish them. Moreover, you can leave off the label for the parameter. My initial summary was simply incorrect. I think this is a function of my not having finished the chapter yet.</i>]</p> <p>Second, both languages support supplying default values for a constructed type. Swift does this via default values defined at the site of the property definition itself, or simply set directly from within an initializer:</p> <pre class="swift"><code>struct Kelvin { var temp: Double = 0.0 // zero kinetic energy!!! init () { temp = 305.0 // Change of plans: maybe just freezing is better } }</code></pre> <p>In Rust, you can not supply default values directly on a property, but you can define any number of custom constructors:</p> <pre class="rust"><code>struct Kelvin { temp: f64, } impl Kelvin { fn abs_zero() -&gt; Kelvin { Kelvin { temp: 0.0 } } fn freezing() -&gt; Kelvin { Kelvin { temp: 305.0 } } }</code></pre> <p>We could of course shorten each of those two one line, so:</p> <pre class="rust"><code>fn abs_zero() -&gt; Kelvin { Kelvin { temp: 0.0 } }</code></pre> <p>The Rust is definitely a little noisier, and that is the downside of this tack. The upside is that these are just functions like any other. This is, in short, <em>exactly</em> the usual trade off we see in the languages.</p> <p>Rust also has the <code>Default</code> trait and the <code>#[derive(default)]</code> attribute for getting some basic defaults for a given value. You can either define a <code>Default</code> implementation yourself, or let Rust automatically do so if the underlying types have <code>Default</code> implemented:</p> <pre class="rust"><code>struct Kelvin { temp: f64, } // Do it ourselves impl Default for Kelvin { fn default() -&gt; Kelvin { Kelvin { temp: 305.0 } } } // Let Rust do it for us: calling `Celsius::default()` will get us a default // temp of 0.0, since that&#39;s what `f64::default()` returns. #[derive(default)] struct Celsius { temp: f64, }</code></pre> <p>This doesn’t get you quite the same thing as Swift’s initializer values. It requires you to be slightly more explicit, but the tradeoff is that you also get a bit more control and flexibility.</p> <p>There’s actually a lot more to say about initializers—there are <em>many</em> more pages in the Swift book about them—but this is already about 1,700 words long, and I’ve been slowly chipping away at it since March (!), so I’m going to split this chapter of the Swift book into multiple posts. More to come shortly!</p> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xv.html"><strong>Previous:</strong> Inheritance: a Swiftian specialty (for now).</a></li> <li><a href="/2016/rust-and-swift-xvii.html"><strong>Next:</strong> More on initializers!</a></li> </ul> <hr /> <section id="addendum-no-late-initialization-in-rust" class="level2"> <h2>Addendum: No Late Initialization in Rust</h2> <p>Returning to the first Rust example—</p> <pre class="rust"><code>#[derive(Debug)] // to make it printable. struct Foo { pub a: i32, pub b: f64, } fn main() { // This will compmile, but `foo` will be useless. let mut foo: Foo; foo.a = 14; foo.b = 42.0; // This would actually fail to compile. Surprising? A bit! // println!(&quot;{:?}&quot;, foo); }</code></pre> <p>You can’t do anything with that data for a few reasons (most of this discussion coming from ubsan, aatch, and niconii on the <a href="https://client00.chat.mibbit.com/?server=irc.mozilla.org&amp;channel=%23rust">#rust-lang IRC</a> back in March):</p> <ol type="1"> <li>Rust lets you “move” data out of a struct on a per-field basis. (Rust’s concept of “ownership” and “borrowing” is something we haven’t discussed a lot so far in this series; my <a href="http://www.newrustacean.com/show_notes/e002/index.html" title="New Rustacean e002: Something borrowed, something... moved?">podcast episode</a> about it is probably a good starting point.) The main takeaway here is that you could return <code>foo.a</code> distinctly from returning <code>foo</code>, and doing so would hand that data over while running the <code>foo</code> destructor mechanism. Likewise, you could pass <code>foo.b</code> to the function created by the <code>println!</code> macro</li> <li>Rust allows you to re-initialize moved variables. I haven’t dug enough to have an idea of what that would look like in practice.</li> <li>Rust treats uninitialized variables the same as moved-from variables. This seems to be closely related to reason #2. The same “I’m not sure how to elaborate” qualification applies here.</li> </ol> <p>I’ll see if I can add some further comments on (2) and (3) as I hit the later points in the Swift initialization chapter.</p> </section> Chris KrychoTue, 07 Jun 2016 23:30:00 -0400tag:v4.chriskrycho.com,2016-06-07:/2016/rust-and-swift-xvi.htmlrustswiftrust-and-swiftprogramming languagesRust and C++ function definitionshttp://v4.chriskrycho.com/2016/03-1801.html<p>I just put my finger on one of the (many) reasons Rust reads better than C++: the visual consistency of its function definitions. Compare—</p> <p>Rust has:</p> <pre class="rust"><code>fn foo() -&gt; i32 { /* implementation */ } fn bar() -&gt; f32 { /* implementation */ }</code></pre> <p>C++ has:</p> <pre class="cpp"><code>int foo() { /* implementation */ } double bar() { /* implementation */ }</code></pre> <p>That consistency adds up over many lines of code. There are many other such choices; the net effect is that Rust is <em>much</em> more pleasant to read than C++.</p> <hr /> <p>Note: I’m aware that C++11 added the <code>auto foo() -&gt; &lt;type&gt;</code> syntax. But this actually <em>worsens</em> the problem. A totally new codebase which uses that form exclusively (which may not always be possible, because the semantics aren’t the same) would have roughly the same visual consistency as Rust <em>in that particular category</em>. (Plenty of others would still be a mess.) But the vast majority of C++ codebases are <em>not</em> totally new. Adding the form means your codebase is more likely to look this this:</p> <pre class="cpp"><code>int foo() { /* implementation */ } auto quux() -&gt; uint32_t { /* implementation */ } double bar() { /* implementation */ }</code></pre> <p>That is, for the record, <em>more</em> visual inconsistency—not less!</p> Chris KrychoFri, 03 Jun 2016 18:01:00 -0400tag:v4.chriskrycho.com,2016-06-03:/2016/03-1801.htmlprogramming languagesrustcplusplusEmber.js: "Introducing Subteams"http://v4.chriskrycho.com/2016/emberjs-introducing-subteams.html<p>In which one tech I really like (<a href="http://emberjs.com">Ember.js</a>) steals a great idea from another tech I really like (<a href="https://www.rust-lang.org">Rust</a>).</p> Chris KrychoTue, 24 May 2016 19:10:00 -0400tag:v4.chriskrycho.com,2016-05-24:/2016/emberjs-introducing-subteams.htmllinksprogramming languagesemberjsrustRust and Swift (xv)http://v4.chriskrycho.com/2016/rust-and-swift-xv.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="http://v4.chriskrycho.com/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <p>The next chapter in the Swift book focuses on <em>inheritance</em>, a concept which does not yet exist in Rust.</p> <p>Swift embraces classical inheritance for <code>class</code> data types. As noted <a href="http://v4.chriskrycho.com/2015/rust-and-swift-x.html">previously</a>, Rust’s <code>struct</code> covers much of the ground covered by Swift’s <code>struct</code> and <code>class</code> types together (value and reference types, etc.). However, what Swift’s <code>class</code> types bring to the table is inheritance-based (and not just composition-based) extension of types.</p> <p>This is a bit of an interesting point: it is an area where, <em>as of today</em>, Swift can do something that is flat impossible in Rust—a rarity.</p> <p>However, the <em>status quo</em> will be changing sometime in the next year or so, as there is a <a href="https://github.com/rust-lang/rfcs/pull/1210">Rust RFC</a> which has been accepted and is in the process of being implemented which paves the way for inheritance. (Discussions are <a href="https://aturon.github.io/blog/2015/09/18/reuse/">ongoing</a> as to the best way to implement it for Rust. Classical inheritance with vtables as in Swift is probably <em>not</em> going to be the approach.)</p> <p>The reason Rust’s core team chose to proceed without inheritance for the 1.0 release of the language last May is simple: at a philosophical level, they prefer (as in general most developers increasingly acknowledge that we should all prefer) composition over inheritance. <em>Prefer</em>, not <em>universally choose</em>, because there are situations in which inheritance is the correct choice. But there is a reason that programming with interfaces rather than via sub-classing is a “best practice” for many scenarios in languages like Java or C#.</p> <p>Rust’s <code>trait</code> system gives you <em>composition</em> in some remarkably powerful ways, allowing you to do things that in C++, for example, have to be accomplished via a combination of inheritance and overloading. Swift, likewise, supplies a <code>protocol</code> system and allows extensions to define further behavior on top of existing data structures. From what I’ve gathered, those approaches are preferred over inheritance in Swift for the same reason Rust shipped 1.0 without it!</p> <p>But Swift does have inheritance, so it’s worth seeing how it works.</p> <p>First, any <code>class</code> which doesn’t declare a parent from which to inherit is a base class. This is an important difference from, say, Python, where all classes inherit from <code>Object</code> (leaving aside custom metaclasses).</p> <p>The syntax choices Swift has made around sub-class declarations are sensible and readable: <code>class SubClass: ParentClass</code> is eminently readable and doesn’t have any obvious points of overlap with other elements in the language.</p> <p>Indeed, <em>many</em> of the choices made around classes are quite sensible. Overrides, for example, are made explicit via the <code>override</code> keyword. While I’ve sometimes poked fun at Swift’s tendency to add keywords everywhere, this seems like a reasonable place to have one, and it’s nice that overrides are explicit rather than implicit. The same is true of the use of <code>super</code> to refer to the superclass. I’m not sure of the implementation details, but <code>super</code> <em>appears</em> to act as just a special/reserved name for an object: all the syntax around it is normal object instance syntax, which is as it should be.</p> <p>The limitations around overriding properties all make sense. You can override a read- or write-only parent property as both readable and writable, but you can’t override a readable or writable property <em>not</em> to be readable or writable respectively. Presumably this is because the method lookup for properties always checks up the inheritance chain for getters or setters, so if one is present, you can’t just get rid of it. (You could of course override with a no-op function that spews a warning or some such, but that would pretty clearly be an abuse of the parent API. There might be times you would do that with a third-party library parent class, but in your own code it should be avoided: it indicates a problem in your API design that you need to address instead.)</p> <p>Finally, we have Swift’s <code>final</code> keyword—and yes, pun intended. It marks whatever block-level item it is attached to—whether class, method, or property—as non-overridable. Attempts to override an item marked final are compile-time failures. (The same kind of thing exists in Java and C#.) In and of itself, this isn’t especially interesting. It is interesting to ponder whether you should make classes subclass-able or not in your API design. There has been <a href="http://mjtsai.com/blog/2015/12/21/swift-proposal-for-default-final/">an active debate</a>, in fact, whether classes in Swift should become final <em>by default</em> in Swift 3.0, rather than open by default. The debate centers on the danger of unintended consequences of overriding, which ultimately takes us back around to the preference for composition, of course.</p> <p>All of this, among other things, raises the very interesting question of what this will look like in Rust when, eventually, we get inheritance there. After all, we know it will be quite different in some ways:</p> <ul> <li><p>It presumably won’t involve a distinct data type constructor, <em>a la</em> Swift’s distinction between <code>struct</code> and <code>class</code>: there may be syntactic sugar involved, and there will definitely be new functionality present, but it will certainly be built on the existing language features as well. There’s a good chance it will basically <em>look</em> like just a special case of <code>impl SomeTrait for SomeStruct</code>, which would fit very well with the ways Rust solves so many other problems.</p></li> <li><p>Rust doesn’t have many of the things which Swift takes care to special-case for overriding with <code>final</code>, but it will need to address that case for inherited methods and data in some way. (The proposal linked above uses a distinction between <code>default</code> and blanket implementations for trait specialization to pull this off; if those words don’t mean anything to you, don’t worry: I’ve read that post and RFC half a dozen times before I got a really solid handle on all the pieces involved.)</p></li> <li><p>It will be a relative latecomer to the language, rather than baked in from the start, and therefore will likely seem a secondary way of solving problems, especially at first. (This is, I think, both intentional and good.)</p></li> </ul> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xiv.html"><strong>Previous:</strong> Indexing and subscripts, or: traits vs. keywords again.</a></li> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xvi.html"><strong>Next:</strong> Initialization: another area where Swift has a lot more going on than Rust.</a></li> </ul> Chris KrychoSat, 12 Mar 2016 14:45:00 -0500tag:v4.chriskrycho.com,2016-03-12:/2016/rust-and-swift-xv.htmlrustswiftrust-and-swiftprogramming languagesRust and Swift (xiv)http://v4.chriskrycho.com/2016/rust-and-swift-xiv.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <p>Rust and Swift both support defining subscript access to a given data type, like <code>SomeType[accessedByIndex]</code>. Unsurprisingly, given <a href="/rust-and-swift.html">everything we’ve seen so far</a>, Rust does this with traits, and Swift with a keyword.</p> <p>In Rust, you can define subscript-style access to a type by implementing the <code>Index</code> and/or <code>IndexMut</code> traits, which allow <em>indexing</em> into a given location in a kind of type. The implementation simply requires one function, which is called when you use the <code>[]</code> operator. That function, <code>index</code> or <code>index_mut</code>, implements how to do the lookup for the specific type. The <code>impl</code> block indicates not only that <code>Index</code> or <code>IndexMut</code> is being implemented, but also the type of the <em>key</em> used: <code>impl Index&lt;Bar&gt; for Foo { ... }</code>, where access would look like <code>a_foo[some_bar]</code>.</p> <p>The two kinds of traits and corresponding methods define the behavior for immutable and mutable data type, as their name suggest.</p> <p>Since the trait is defined generically, you can implement whatever kinds of accessors you like to the same underlying data structure, including generics accessors with trait bounds.</p> <p>It is perhaps telling that in Rust you just find these traits in the general <code>std::ops</code> module, where all the core language operations and associated operators are defined. Rust doesn’t do “operator overloading” so much as it simply provides operators as one more class of trait potentially applicable to your type. (The family resemblance to Haskell’s type classes and similar in other languages is obvious.)</p> <p>In Swift, you define indexing behavior with the <code>subscript</code> keyword. Subscripts act very similarly to Swift’s <a href="http://v4.chriskrycho.com/2016/rust-and-swift-xii.html">computed properties</a>. They can be made read- or write-only by including or excluding <code>get</code> and <code>set</code> function definitions, just like computed properties.</p> <p>The behavior is in fact so closely aligned with the computed property syntax and behavior that I initially wondered if it wasn’t just a special case. It is not (though I’m sure much of the parsing machinery can be shared). As the designation of <code>subscript</code> as a keyword strongly implies, and unlike in Rust, this is a separate language construct, not building on existing language machinery.</p> <p>Swift, like Rust, allows you to define arbitrary accessors. However, since the behavior relies on the <code>subscript</code> construct rather than generics and protocols (Swift’s equivalent to Rust’s traits), you define different kinds of accessors via multiple <code>subscript</code> blocks. (Presumably these could take generic arguments, but I haven’t tested that to be sure.)</p> <p>Both languages proceed to use these as ways of accessing types as makes sense—e.g. for not only arrays or vectors, but also dictionaries in Swift and <code>HashMap</code> types in Rust.</p> <p>Since you can define the behavior yourself, you can also use complex types as keys. The languages approach this a bit differently, though. In Rust, if you wanted a compound key, you would need to define either a simple container <code>struct</code> or use a tuple as the argument. In Swift, because it uses the same basic syntax as computed properties, you can just define as many method arguments, of whatever type, as you want.</p> <p>Takeaway: Rust uses traits; Swift uses a keyword. We probably could have guessed that when we started, at this point!</p> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xiii.html"><strong>Previous:</strong> Methods, instance and otherwise.</a></li> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xv.html"><strong>Next:</strong> Inheritance: a Swiftian specialty (for now).</a></li> </ul> Chris KrychoThu, 10 Mar 2016 21:25:00 -0500tag:v4.chriskrycho.com,2016-03-10:/2016/rust-and-swift-xiv.htmlrustswiftrust-and-swiftprogramming languagesStatic Site Generators and Podcastinghttp://v4.chriskrycho.com/2016/static-site-generators-and-podcasting.html<p>Presently, I publish both <a href="http://www.winningslowly.org/">Winning Slowly</a> and <a href="http://www.newrustacean.com/">New Rustacean</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> using what is admittedly a bit of a quirky approach. It works well for me, and I think it’s worth documenting for other nerdy types out there, but if you’re just getting going with podcasting and you’re looking for the easy way to do it, let me warn you: <em>this isn’t it</em>. Something like <a href="https://soundcloud.com/for/podcasting">SoundCloud</a> and a blog for show notes, or <a href="https://wordpress.org">WordPress</a> with <a href="https://wordpress.org/plugins/powerpress/">Blubrry PowerPress</a> is what you want instead. This approach works <em>extremely</em> well for statically-generated sites, however, and I imagine a few people out there might find it useful.</p> <section id="the-short-version" class="level2"> <h2>The short version</h2> <ul> <li>Generate the feeds with <a href="http://reinventedsoftware.com/feeder/">Feeder</a>.</li> <li>Generate the site statically with something else (and it <em>really</em> doesn’t matter what).</li> <li>Copy the feed into the generated site.</li> </ul> </section> <section id="the-long-version" class="level2"> <h2>The long version</h2> <p>I generate the sites themselves with <a href="http://docs.getpelican.com/en/3.6.3/">Pelican</a> and <a href="http://www.newrustacean.com/show_notes/e001/index.html"><code>cargo doc</code></a>, respectively. I was already comfortable with Pelican because it’s what I use to generate <em>this</em> site (with a few <a href="https://github.com/chriskrycho/chriskrycho.com/blob/master/pelicanconf.py">tweaks</a> to the standard configuration, especially using <a href="http://pandoc.org/">Pandoc</a> rather than the Python Markdown implementation), so I ran with it for building the Winning Slowly site, and it has worked quite well for building the site itself. It just gets built locally and deployed via <a href="https://pages.github.com/">GitHub Pages</a>.</p> <p>However, it does not have built-in support for generating <a href="https://en.wikipedia.org/wiki/RSS_enclosure">podcast feeds</a>, even just the general case with enclosures. <a href="https://itunespartner.apple.com/en/podcasts/overview">iTunes podcast support</a> would have taken a lot of work to add.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> Instead, I chose to build the RSS feed semi-manually. <em>Semi</em>-manually, because doing it totally manually is a recipe for making mistakes. XML is many things, but “easy to write correctly by hand” is not one of them. I use <a href="http://reinventedsoftware.com/feeder/">Feeder</a> to manage the feeds, and <em>it</em> makes sure that the enclosure and iTunes elements are set correctly.</p> <p>The biggest upside to this is that I can use Pelican without modification to how it generates feeds (apart from optionally turning them off entirely). It just <a href="https://github.com/WinningSlowly/winningslowly.org/blob/master/pelicanconf.py#L99">copies</a> the feed I generate to the output file during its normal build process. As suggested above, I also <em>don’t</em> generate the other feeds which Pelican supports, as we have no need for them; we only care about the podcast feed.</p> <p>This process works equally well, with very little modification, for New Rustacean. In that case, I’m generating the content by running Rust’s documentation tool, <code>cargo doc</code><a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> to render the “API docs” which serve as show notes. Notice the family resemblance between <a href="http://www.newrustacean.com/show_notes/">my “show notes”</a> and, say, the <a href="http://sgrif.github.io/diesel/diesel/index.html">Diesel docs</a>, which are both generated the same way. This is <em>not</em> a normal way of building a podcast website; you can hear me explain why I did it this way in <a href="http://www.newrustacean.com/show_notes/e001/index.html">New Rustacean e001: Document all the things!</a> In any case, I just take the show note-relevant parts of the documentation and put it in Feeder, generate the feed, and <a href="https://github.com/chriskrycho/newrustacean.com/blob/master/Makefile#L32">copy that as part of the build process</a>.</p> <p>That’s it!</p> </section> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>And, incidentally, <a href="http://www.sap-py.com">Sap.py</a> and my <a href="http://v4.chriskrycho.com/sermons.xml">sermons</a> feed.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn2" role="doc-endnote"><p>If I stick with Pelican long-term, I might look into adding it anyway, but honestly, I don’t love Pelican. The reasons have little to do with Pelican for itself, and a lot more to do with my particular and somewhat peculiar needs. That’s a post for another day. In any case, I’m likelier to use another generator—even one I write myself!—than to do the work to make Pelican do what I want.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn3" role="doc-endnote"><p>Technically, Rust’s documentation tool is <code>rustdoc</code>, which <code>cargo doc</code> wraps around. I never actually use <code>rustdoc</code> directly, though.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoSun, 28 Feb 2016 12:50:00 -0500tag:v4.chriskrycho.com,2016-02-28:/2016/static-site-generators-and-podcasting.htmlsoftware developmentpodcastingpythonrustRust and Swift (xiii)http://v4.chriskrycho.com/2016/rust-and-swift-xiii.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <p>Rust and Swift both have methods which are attached to given data types. However, whereas Rust takes its notion of separation of data and functions rather strictly, Swift implements them on the relevant data structures (classes, structs, or enums) directly. In other words, the implementation of a given type’s methods is within the body of the type definition itself in swift, whereas in Rust it is in an <code>impl</code> block, usually but not always immediately adjacent in the code.</p> <p>This goes to one of the philosophical differences between the two languages. As we’ve discussed often in the series, Rust reuses a smaller set of concepts—language-level primitives—to build up its functionality. So methods on a type and methods for a trait on a type are basically the same thing in Rust; they’re defined in almost exactly the same way (the latter includes <code>for SomeTrait</code> in the <code>impl</code> expression). In Swift, a method is defined differently from a protocol definition, which we’ll get to in the future. The point is simply this: the two take distinct approaches to the relationship between a given type definition and the implementations of any functions which may be attached to it.</p> <p>Another important difference: access to other members of a given data type from within a method is <em>explicit</em> in Rust and <em>implicit</em> in Swift. In Rust, the first parameter to an instance method is always <code>self</code> or <code>&amp;self</code> (or a mutable version of either of course), much as in Python. This explicitness distinction is by now exactly what we expect from the two languages.</p> <p>Both use dot notation, in line with most other languages with a C-like syntax, for method calls, e.g. <code>instance.method()</code> in Swift and <code>instance.method()</code> in Rust. The latter is just syntactical sugar for <code>T::method(&amp;instance)</code> or <code>T::method(instance)</code> where <code>T</code> is the type of the instance (depending on whether the item is being borrowed or moved). Given its implicit knowledge of/access to instance-local data, and the distinctive behavior of Swift methods (see below), I don’t <em>think</em> the same is, or even could be, true of Swift.</p> <p>All of Swift’s <a href="http://v4.chriskrycho.com/2015/rust-and-swift-viii.html">other behaviors around functions</a>—internal and external names, and all the distinctions that go with those—are equally applicable to methods. Similarly, with the sole change that the first parameter is always the instance being acted on, a Rust methods follow all the same rules as ordinary Rust functions (which is why you can call the struct or enum method with an instance parameter as in the example above).</p> <p>Swift does <em>have</em> a <code>self</code>—it is, of course, implicit. It’s useful at times for disambiguation—basically, when a parameter name shadows an instance name. This will look familiar to people coming from Ruby.</p> <p>The strong distinction Swift makes <a href="http://v4.chriskrycho.com/2015/rust-and-swift-x.html">between reference and value types</a> comes into play on methods, as you might expect, as does its approach to mutability. Methods which change the values in value types (<code>struct</code> or <code>enum</code> instances) have to be declared <code>mutating func</code>. This kind of explicit-ness is good. As we discussed in <a href="http://v4.chriskrycho.com/2015/rust-and-swift-x.html">Part 10</a>, Rust approaches this entire problem differently: types are not value or reference types; they are either mutable and passed mutably (including as <code>mut self</code> or <code>&amp;mut self</code>), or they are not. If an instance is mutable and passed mutably, a method is free to act on instance data. And in fact both languages require that the instance in question not be immutable. In fact, everything we said in Part 10 about both languages applies here, just with the addendum that private properties are available to methods.</p> <p>The distinction, you’ll note, is in where the indication that there’s a mutation happens. Swift has a special keyword combination (<code>mutating func</code>) for this. With Rust, it’s the same as every other function which mutates an argument. This makes Rust slightly more verbose, but it also means that in cases like this, the existing language tooling is perfectly capable of handling what has to be a special syntactical case in Swift.</p> <p>Both Swift and Rust let you out-and-out change the instance by assigning to <code>self</code>, albeit in fairly different ways. In Swift, you’d write a mutating method which updates the instance proper like this:</p> <pre class="swift"><code>struct Point { var x = 0.0, y = 0.0 mutating func changeSelf(x: Double, y: Double) { self = Point(x: x, y: y) } }</code></pre> <p>In Rust, you’d need to explicitly pass a mutable reference and dereference it. (If you tried to pass <code>mut self</code> instead of <code>&amp;mut self</code>, it would fail unless you returned the newly created object and assigned it outside.) Note that while the full implementation here is a couple lines longer, because of the data-vs.-method separation discussed earlier, the implementation of the method itself is roughly the same length.</p> <pre class="rust"><code>pub struct Point { pub x: f64, pub y: f64, } impl Point { pub fn change_self(&amp;mut self, x: i32, y: i32) { *self = Point { x: x, y: y }; } }</code></pre> <p>Note that though you <em>can</em> do this, I’m not sure it’s particularly Rustic. My own instinct would be to get a <em>new</em> <code>Point</code> rather than mutate an existing one, in either language, and let the other be cleaned up “behind the scenes” as it were (with automatic memory management in Swift or the compiler’s automatic destruction of the type in Rust)—purer functions being my preference these days.</p> <p>You can do this with <code>enum</code> types as well, which the Swift book illustrates with a three-state switch which updates the value type passed to a new value when calling its <code>next()</code> method. You can do the same in Rust, with the same reference/dereference approach as above.</p> <p>Here’s a three-state switch in Swift:</p> <pre class="swift"><code>enum ThreeState { case First, Second, Third mutating func next() { switch self { case First: self = Second case Second: self = Third case Third self = First } } }</code></pre> <p>And the same in Rust:</p> <pre class="rust"><code>enum ThreeState { First, Second, Third } impl ThreeState { pub fn next(&amp;mut self) { match *self { ThreeState::First =&gt; *self = ThreeState::Second, ThreeState::Second =&gt; *self = ThreeState::Third, ThreeState::Third =&gt; *self = ThreeState::First, } } }</code></pre> <p>Both languages also have what Swift calls “type methods”, and which you might think of as “static class methods” coming from a language like Java or C♯. In Swift, you define them by adding the <code>static</code> or <code>class</code> keywords to the <code>func</code> definition. The <code>class func</code> keyword combo is only applicable in <code>class</code> bodies, and indicates that sub-classes may override the method definition.</p> <pre class="swift"><code>struct Bar { static func quux() { print(&quot;Seriously, what&#39;s a `quux`?&quot;) } } func main() { Bar.quux() }</code></pre> <p>In Rust, you simply drop <code>self</code> as a first parameter and call it with <code>::</code> syntax instead of <code>.</code> syntax:</p> <pre class="rust"><code>struct Bar; impl Bar { pub fn quux() { println!(&quot;Seriously, what&#39;s a `quux`?&quot;); } } fn main() { Bar::quux(); }</code></pre> <p>As usual, Rust chooses to use existing language machinery; Swift uses new (combinations of) keywords.</p> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xii.html"><strong>Previous:</strong> Properties: type and instance, stored and computed.</a></li> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xiv.html"><strong>Next:</strong> Indexing and subscripts, or: traits vs. keywords again.</a></li> </ul> Chris KrychoSun, 28 Feb 2016 11:15:00 -0500tag:v4.chriskrycho.com,2016-02-28:/2016/rust-and-swift-xiii.htmlprogramming languagesrustswiftrust-and-swiftRust and Swift (xii)http://v4.chriskrycho.com/2016/rust-and-swift-xii.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <p><i class="editorial">A note on publication: I had this drafted in early January and simply forgot to publish it. Whoops!</i></p> <hr /> <ul> <li><p>As noted in <a href="http://v4.chriskrycho.com/2015/rust-and-swift-x.html">my discussion of the product types in Rust and Swift</a>, Swift distinguishes between classes and structs, with the former being reference types and the latter being value types. All structs are value types in Rust. (That you can wrap them in a pointer for heap-allocation with one of the smart pointer types, e.g. <code>Box</code> or <code>Rc</code> or <code>Arc</code>, doesn’t change this fundamental reality.) This underlying difference gives rise to one the big difference between Swift classes and Rust structs: a constant <code>class</code> instance in Swift can still have its fields mutated; not so with a Rust <code>struct</code> instance. But also not so with a <em>Swift</em> <code>struct</code> instance, as it turns out! There isn’t a straightforward way to do this with <code>Box&lt;T&gt;</code> in Rust; you <em>could</em> do it with something like an <code>Rc&lt;T&gt;</code> or <code>Arc&lt;T&gt;</code>, though.</p></li> <li><p>Swift’s <code>lazy</code> keyword, and associated delayed initialization of properties has, as far as I know, no equivalent whatsoever in Rust. And while I can see the utility in principle, I’m hard-pressed to think of any time in my working experience where the behavior would actually be useful. Rather than having <code>lazy</code> properties, I would be far more inclined to separate the behavior which should be initialized at a later time into its own data structure, and supplying it via <em>inversion of control</em> if it is necessary for an actions taken by other data structures. (This seems—at first blush at least—to be a way of supporting the un- or partially-initialized data types possible in Objective C?)</p></li> <li><p>Swift has computed properties, a concept familiar to Python developers (and relatively recently introduced in JavaScript). These can be quite handy, as they let you define a property to be accessed like any other (<code>someInstance.theProperty</code>) while being defined with functions which compute the value dynamically. A common, trivial example: if you defined a <code>Person</code> with <code>firstName</code> and <code>lastName</code> members, you could define a computed property, <code>fullName</code>, which was built using the existing values.</p></li> <li><p>Rust doesn’t have computed properties at all. This is because of its design decision to deeply separate <em>data</em> from <em>behavior</em>, essentially stealing a page from more pure-functional languages (Haskell etc.). This is (one reason) why you don’t define the implementation of a <code>struct</code> method in the same block as the members of the struct. See an excellent explanation <a href="https://www.reddit.com/r/rust/comments/2uvfic/why_doesnt_rust_have_properti%20es/cocmunq">here</a>.</p></li> <li><p>It’s also closely related the way Rust favors composition over inheritance (by making the latter impossible, at least for now!). By separating <code>impl</code> from <code>struct</code> and <code>enum</code>, Rust makes it not only straightforward but <em>normal</em> to define new behavior for a given item separately from the data description. This, combined with the use of traits (like Swift’s protocols) as the primary way of sharing behavior between objects, means that you don’t have to worry about conforming to some interface when you define a given type; it can always<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> be defined later, even by entirely other modules or even other crates (packages).</p></li> <li><p>In any case, the result is that it’s not at all Rustic<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> to have something like getters or setters or computed properties. It makes sense to have them in Swift, though, which has a more traditionally object-oriented type system (though with some neat additions in the form of its <code>protocol</code> type classes, which are analogous to Rust’s <code>trait</code>s—but we’ll come to those in a future post). This is a wash: it’s just a function of the slightly different approaches taken in object design in the two systems. If you have a Swift-style type system, you should have computed properties. If you have a Rust-like type system, you shouldn’t.</p></li> <li><p>I’m shocked—utterly shocked!—to find that Swift provides a default <code>newValue</code> argument for setters for computed properties, and shorthand for defining read-only properties. By which I mean: I find this kind of thing entirely unsurprising at this point in Swift, but I don’t like it any better. Making so much implicit just rubs me the wrong way. Once you know the language, it’s fine of course: you’ll recognize all the patterns. It just seems, in an interesting way, to add cognitive load rather than reducing it. That may just be me, though!</p></li> <li><p>Interestingly, Swift also allows you to set watchers on given properties—functions called with the new or the removed value whenever the value of the computed property is updated or touched for any reason. It has two of these built in: <code>willSet</code> and <code>didSet</code>. You can override these to get custom behavior when a normal property is about to change. (You can of course just implement the desired behavior yourself in the <code>set</code> method for a computed property.)</p></li> <li><p>Since Rust doesn’t have properties, it doesn’t have anything analogous. I can’t think of a particularly straightforward way to implement it, either, though you might be able do some chicanery with a trait. Of course you can always define a setter method which takes a value and optional callbacks for actions to take before and after setting the value; the thing that’s nice in Swift is that it gives you these as built-in capabilities within the language itself. (Now I’m wondering if or how you could implement an <code>Observable</code> trait, though! Might have to play with that idea more later.) It’s worth remembering , in any case, that Rust doesn’t have these <em>because it doesn’t have properties</em>.</p></li> <li><p>Curiously, Swift provides the same functionality for “global” and “local” variables in a given context. In both cases, this is suggestive of the underlying object model for both modules and functions in Swift.</p></li> <li><p>Now I’m curious what the representation of a module is in Swift; is it part of the general object system in some way?</p></li> <li><p>This likewise gets me asking: what <em>is</em> a module in Rust? It’s a block item, clearly, and accordingly defines a scope (as do functions, if and match expressions, and so on). It’s <em>not</em> a compilation unit (as it is in C or C++). What other machinery is attached to it?</p></li> <li><p>Both of these questions can be answered by reading the source code for the languages (<a href="https://github.com/rust-lang/rust">Rust</a>, <a href="https://github.com/apple/swift">Swift</a>), of course. Putting that on my to-do list.</p></li> <li><p>Swift also has <em>type properties</em>: values common to all instances of a given type. These are directly analogous to <em>class properties</em> (or <em>class attributes</em>) in Python or prototype properties in JavaScript.</p></li> <li><p>Rust doesn’t have anything like this to my knowledge. You could accomplish something similar using a module-level variable with a <code>'static</code> lifetime,<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> much as you could in C—but that wouldn’t be an item on the type itself, of course.</p></li> <li><p>The <code>static</code> declaration of item in Swift suggests what a possible implementation might look like in Rust: defining a member like <code>a_static_long: 'static i64</code>. There might be some interesting challenges around that, though; I don’t know enough to comment meaningfully. At the least, it seems like it would be an odd fit with the rest of the memory management approach Rust takes, and it would make it a bit harder to reason correctly about the behavior of data in a given type. (There are certainly issues there around mutability guarantees and lifetime checking!)</p></li> <li><p>Because of the differences in underlying approach to data types and implementation, this is one of the areas where the superficially (and sometimes actually) similar languages diverge <em>a lot</em>.</p></li> </ul> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xi.html"><strong>Previous:</strong> Hopes for the next generation of systems programming.</a></li> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xiii.html"><strong>Next:</strong> Methods, instance and otherwise.</a></li> </ul> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>leaving aside details about <code>trait</code> specialization <a href="https://github.com/aturon/rfcs/blob/impl-specialization/text/0000-impl-specialization.md">still being hashed out</a> in Rust<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn2" role="doc-endnote"><p>This is now my preferred term for “idiomatic Rust”—directly analogous to “Pythonic,” but with the upside of being an actual word, and one with pleasantly evocative connotations to boot.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn3" role="doc-endnote"><p>There’s nothing analogous to Rust’s concept of explicit lifetimes in Swift, as far as I can tell. The <code>static</code> keyword in Swift, like that in C, Objective-C, and C++, is <em>sort of</em> like Rust’s <code>'static</code> lifetime specifically, for variables at least—but Rust’s lifetime is substantially more sophisticated and complex than that analogy might suggest.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoSat, 27 Feb 2016 22:30:00 -0500tag:v4.chriskrycho.com,2016-02-27:/2016/rust-and-swift-xii.htmllisticlessoftware developmentrustswiftrust-and-swift“I Don't Know When I'd Use That”http://v4.chriskrycho.com/2016/i-dont-know-when-id-use-that.html<p>I was reading an interesting Stack Overflow <a href="http://stackoverflow.com/questions/21170493/when-are-higher-kinded-types-useful">discussion</a> of the value of <a href="http://stackoverflow.com/questions/6246719/what-is-a-higher-kinded-type-in-scala">higher-kinded types</a> (hereafter <abbr>HKTs</abbr>), and noted someone repeatedly commenting, “But when would you use this in a <em>real app</em>?” To put it the way another <a href="https://m4rw3r.github.io/rust-and-monad-trait/">blog post</a> about <abbr>HKTs</abbr> (in Rust), they are “a feature people do not really know what to do with.”</p> <p>Don’t get me wrong: I’m sympathetic to that desire for concrete examples. I’m interested in these kinds of things not primarily for their intellectual value but for their pragmatic value (though I don’t think those two are as distinct as many people do). I’d <em>also</em> love to see some more real-world examples in those discussions. All too often, the discussions of types in Haskell end up being quite abstract and academic—no surprise, given the language’s origin. But I’m also aware that quite often it’s difficult to see how a given kind of abstraction is useful without jumping into a language which has that abstraction available and <em>using</em> it.</p> <p>People often get turned off by Haskell (and other similarly high-abstraction languages like Scala) because of challenging terms like <em>monad</em>, <em>applicative</em>, <em>functor</em>, and so on. And again: I get that. To grok Haskell, you need to wrap your head around a lot of <em>math</em> ideas—mainly various properties of <em>sets</em>.</p> <p>But I remember feeling the same way six years ago when I started playing with JavaScript and jQuery and every tutorial out there simply assumed existing familiarity and comfort with functions as arguments or return values. Coming from the world of Fortran and C, my head ached for weeks as I tried to make sense of what I was seeing. Even when I finally got it, <em>I didn’t like it</em>. Over the last several years, though, I’ve become increasingly comfortable and even reliant on closures, composition of functions to transform data, and so on as I worked regularly in Python and JavaScript.</p> <p>That experience has taught me that my current inability to see the utility of a given abstraction means little about the abstraction. It’s primarily an indicator of my own inexperience.</p> <p>To the question of the utility <abbr>HKTs</abbr> in general—in Haskell, Rust, or somewhere else—I don’t have the knowledge myself (yet) to supply a good answer. Heck, I can’t even <em>explain</em> them very well. (<a href="http://adriaanm.github.io/research/2010/10/06/new-in-scala-2.8-type-constructor-inference/">Other people can, though!</a>) But I can say that reading <a href="https://gumroad.com/l/maybe-haskell"><em>Maybe Haskell</em></a> showed me clearly that such things can be very useful. Even if I am not yet comfortable using that tool, I see how learning to use it would be profitable in the long-term. And like any good tool, even if you don’t need it every day… when you want it, you <em>really</em> want it.</p> Chris KrychoSun, 17 Jan 2016 10:00:00 -0500tag:v4.chriskrycho.com,2016-01-17:/2016/i-dont-know-when-id-use-that.htmlsoftware developmentprogramming languagesrusthaskellWomen in Rusthttp://v4.chriskrycho.com/2016/women-in-rust.html<p><i class=editorial>I posted these bullet points last night as a series of tweets on my <a href="https://www.twitter.com/chriskrycho">main account</a>.</i></p> <ul> <li><p><a href="https://twitter.com/chriskrycho/status/686007510147309568">∞ January 9, 2016 21:11</a></p> <blockquote> <p>A thing I’d really, really like to see change—this is from the <a href="http://www.newrustacean.com/">New Rustacean</a> Twitter data. Unsurprising, but awful:</p> <figure> <img src="//cdn.chriskrycho.com/images/new-rustacean-followers.png" alt="@newrustacean Twitter follower gender data" /><figcaption><a href="https://www.twitter.com/newrustacean">@newrustacean</a> Twitter follower gender data</figcaption> </figure> </blockquote></li> <li><p><a href="https://twitter.com/chriskrycho/status/686007729371148289">∞ January 9, 2016 21:12</a></p> <blockquote> <p>Takeaway: the <a href="https://www.twitter.com/rustlang">@rustlang</a> community has many strengths, but like every tech community, we need to improve here—a lot.</p> </blockquote></li> <li><p><a href="https://twitter.com/chriskrycho/status/686008145752272896">∞ January 9, 2016 21:14</a></p> <blockquote> <p>Standing offer: if you’re a female <a href="https://www.twitter.com/rustlang">@rustlang</a> dev, I’d <em>love</em> to feature your experience learning Rust on the show.</p> </blockquote></li> <li><p><a href="https://twitter.com/chriskrycho/status/686008527937245185">∞ January 9, 2016, 21:15</a></p> <blockquote> <p>I’ll be doing some interview <a href="https://www.twitter.com/newrustacean">@newrustacean</a> episodes soon-ish—I want as many female voices in the mix as possible.</p> </blockquote></li> </ul> Chris KrychoSun, 10 Jan 2016 15:25:00 -0500tag:v4.chriskrycho.com,2016-01-10:/2016/women-in-rust.htmlpodcastingtweetstormrustRust and Swift (xi)http://v4.chriskrycho.com/2016/rust-and-swift-xi.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <p>I’ve still been (slowly) working through the Swift book and comparing Swift and Rust; I have another draft started which I’ll hopefully finish this week. And I still find the comparison deeply profitable. The two languages continue to evolve in interesting ways, and the comparison is all the more interesting <a href="https://github.com/apple/swift">now that Swift is open-source</a> and its future <a href="https://github.com/apple/swift-evolution">open for community input</a> (just as <a href="https://github.com/rust-lang/rfcs">Rust is</a>).</p> <p>Something I’ve been thinking about for several months, and which the <a href="https://overcast.fm/+CdSzsTIY/1:16:42">brief discussion of Swift, Go, and Rust</a> at the end of the latest <a href="http://atp.fm/episodes/151">Accidental Tech Podcast</a> brought back to my mind, is the question of what the next generation of systems-level programming language should be. And my answer is: there shouldn’t be <em>just one</em>. The best possible thing for the space, in many ways, is for there to be a healthy diversity of options and lots of competition in the space. We don’t want to have <em>ten</em> different systems programming languages to deal with, I think—but three or four or five would be <em>much</em> preferable to having one or two (closely related) as we have in the decades of C and C++ dominance.</p> <p>Don’t get me wrong: both languages (and perhaps especially C) do many things exceptionally well. For all that they are (justly) maligned for some of their problems, the longevity of both C and C++ has a great deal to do with how well they fit the problem domain, and how much they’ve empowered developers to accomplish within that space (which is very, <em>very</em> large).</p> <p>The problem, though, at least as I see it, is that the existence of only two really serious systems programming languages for the last several decades has led a lot of developers to think that C and C++‘s ways of solving problems are the <em>only</em> way to solve problems. The languages we use shape the way we think about possible solutions, and when a given language doesn’t recognize entire classes of different approaches, that deeply limits developers’ ability to tackle certain issues. (See also the interesting CppCast <a href="http://cppcast.com/2015/10/andrei-alexandrescu/">interview with D’s Andrei Alexandrescu</a> in which he makes similar points.)</p> <p>The most obvious thing missing from both is the ability to do truly functional-style programming. C of course is also lacking classes and thus is much more difficult to use for any sort of object-oriented programming.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> Neither has anything remotely like Rust’s traits or Swift’s extensions; C++ has only gotten lambdas recently.</p> <p>All of this comes out to mean that the set of <em>tools</em> available to systems programmer has necessarily been missing any number of things available in languages outside that context. In some cases, this may be a necessary consequence of the kinds of programming being done: when you need totally deterministic memory and compiler behavior, dynamic typing and a non-trivial runtime are simply not options. But in many cases, they are simply a function of the history of the languages’ development and history. Being an ALGOL descendant, and especially a C descendant, means there are some fundamental choices about the language which will differ from those made in a language descended from ML.</p> <p>All of which is to say: C and C++ have been really useful tools in many ways, but having <em>only</em> C and C++ available for serious systems programming work over the last decades has left many developers blind to or simply unaware of the real advantages other paradigms might offer them.</p> <p>So going forward, I don’t want there to be <em>a winner</em> in the systems programming space. I’d rather see D, Rust, Swift, Go, and maybe even a few other contenders all stay strong—finding their own niches and continually pushing each other and learning from each other. That will give us a space in which different languages are free to try out different approaches to the same problems, without being tied to the specific constraints faced by other languages. Built-in greenthreading? Go! Hindley-Milner types, memory safety, and zero runtime? Rust! Something in beween, highly expressive and with different type systems and tradeoffs around memory management, etc.? Swift, or D!</p> <p>Having a robust, thriving set of competitors in the market will be good for the languages themselves. But it will also be good for developers. It will take off some of the blinders that come from a single language (or a pair of very closely related languages) dominating the ecosystem. It will make it likelier that people will be more familiar with different programming paradigms. And that can only be a good thing, as far as I’m concerned.</p> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-x.html"><strong>Previous:</strong> Classes and structs (product types), and reference and value types.</a></li> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xii.html"><strong>Next:</strong> Properties: type and instance, stored and computed.</a></li> </ul> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>It is of course entirely possible to do non-classical OOP; the point is that C entirely lacks <em>language-level</em> facilities for OOP, inheritance, etc.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoSun, 10 Jan 2016 10:00:00 -0500tag:v4.chriskrycho.com,2016-01-10:/2016/rust-and-swift-xi.htmlsoftware developmentrustswiftrust-and-swiftprogramming-languagesThoughts on 2015 (and 2016)http://v4.chriskrycho.com/2015/thoughts-on-2015-and-2016.html<p>As we come to the end of the year, I have been reflecting on the things I set out to do this year, and on my hopes for the coming year. At the start of the year, I posted a number of goals for my “public” life this year, and I also wrote up a number of personal goals for myself. Goals are well and good, but if I do not evaluate how I did on them, and think about areas I succeeded and areas I failed, and on how I might do better in the future, those goals will not make much difference. (<em>Much</em> difference, I say, because I have long found that even just having goals makes a difference in how I approach the year.)</p> <p>At the start of the year, I posted a list of <a href="http://v4.chriskrycho.com/2015/public-ish-plans.html">“Public-ish Plans”</a>. My self-evaluation on those counts isn’t amazing. The Winning Slowly goals, I managed: we have separate pages for each season, and we recorded two more seasons—each one better than those before. Hosting things on Digital Ocean and migrating my wife’s blogs off of Blogger and WordPress, not so much (read: not at all, though I did <em>start</em> writing a Ghost theme for her current WordPress site… and haven’t touched it in at least six months.) I wrote some music this year, but not three minutes worth—you <em>can</em> hear all 37 seconds of it <a href="https://soundcloud.com/chriskrycho">on SoundCloud</a>. I wrote <a href="http://v4.chriskrycho.com/poetry/">poetry</a>; I managed to average about one poem a month starting in March. I wrote a few essays, but nothing close to one per month. I posted a whopping two book reviews (out of the six I hoped for), and both of those were written for school. I managed to add a picture to the About page, but I didn’t even come close to blogging about the family on a monthly basis.</p> <p>In sum: about 50/50 on those goals.</p> <p>That said, I managed quite a few other things <em>not</em> on that list this year. I started learning Rust, and started <a href="http://newrustacean.com/">a podcast about it</a> which is easily the most successful online endeavor I’ve ever undertaken, with a good 500 regular listeners. (That’s a small crowd on the internet, but massively more than any writing I’ve done, and actually larger than Winning Slowly’s current audience.) I have basically carried home a major transition effort for my main software development client, and helped them bring a new developer up to speed. I landed a new software development job, doing things I’m much more passionate about, which I’ll be starting in mid-January. I ran a triathlon (and placed third in my age group), and I set another personal record in the half-marathon I ran this fall.</p> <p>One of the lessons I take away from this last year, then, is that it’s important to set goals, but it’s also important to let those goals change over time. Some of those goals are still things I’d like to accomplish—like migrating us to DigitalOcean, and getting Jaimie’s sites off of Blogger especially. Another (fairly obvious one) is prioritizing. I had a lot of major goals for last year, and in retrospect, I think I had <em>too many</em>. It’s hard to keep all of those in sight of the course of the year, especially with other professional and scholastic demands to meet (themselves often good in their own right).</p> <p>With all of these things in mind, I’m planning to approach 2016 a little differently. I haven’t made formal goals yet, but I have come up with the basic outline I want to use going forward.</p> <p>First, I am going to set a single goal in each of five major categories in my life:</p> <ul> <li><strong>spiritual:</strong> everything in my walk with God, including my own personal devotions, my involvement in the life of the church, and my “ministry” actions in general</li> <li><strong>family:</strong> both quantity and quality time spent with my wife and my quickly-growing-up little girls</li> <li><strong>personal:</strong> podcasting, blogging, and writing for <a href="http://mereorthodoxy.com/author/chris-krycho/">other outlets</a></li> <li><strong>professional:</strong> working in my new job and as a consultant, and carrying on toward the conclusion of my M. Div.</li> <li><strong>health/fitness:</strong> continuing to stay healthy, including eating well and continuing to stay fit by running and doing triathlon work</li> </ul> <p>Note that this list is intentionally <em>unordered</em>.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> My spiritual life remains the highest priority, because if my walk with God falters, everything else will go amok. Beyond that, however, the amount of time and effort I invest in each category not only can but should vary over time. Family will broadly remain in the second of those slots, though there may be days or the occasional week where one of the other concerns <em>very temporarily</em> takes a higher priority. The others will adjust relative to each other as need be: there will be times when school requires more, and so my own writing gets less time, and there will be times when I have more flexibility and so am able to devote more to those personal interests, and so on. The goal here is not the mythical notion of “balance” but rather faithfulness, which has some superficial similarities but ultimately <a href="http://v4.chriskrycho.com/2015/faithfulness.html">plays out rather differently</a>.</p> <p>I’m hoping, in light of those goals, to set annual, monthly, and daily goals in each of those categories. The daily goals should help me move toward the monthly goals, and the monthly goals toward the yearly goals. I only get to set one goal in each of those categories for each tier: at five goals, that’s already plenty! I hope that evaluating each day will help me be more focused and faithful, and that situating daily and monthly goals each in light of larger goals will help me actually accomplish those larger goals. We’ll see how it goes, of course. I’ll be back in a week or so with whatever goals I decide to make public in those categories, and again in a year with an evaluation rather like this one.</p> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>Under the covers, it’s literally an HTML unordered list.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoSat, 26 Dec 2015 13:30:00 -0500tag:v4.chriskrycho.com,2015-12-26:/2015/thoughts-on-2015-and-2016.htmlfamilyrustpodcastingRust and Swift (x)http://v4.chriskrycho.com/2015/rust-and-swift-x.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <ul> <li><p>Swift and Rust both have “product types” as well as the <code>enum</code> “sum types.” In Rust, these are <code>struct</code> types; Swift splits them into <code>class</code>es and <code>struct</code>s.</p></li> <li><p>“Product types” will be much more familiar to programmers coming from a C-like background, or indeed most object-oriented programming languages: these are the same basic kind of thing as classes, structs, and objects in other languages. These include <em>all</em> the value types which compose them, unlike sum types—<code>enum</code>—which have <em>only one</em> of the value types which compose them.</p></li> <li><p>Right off the bat, I note the Swift book’s somewhat amusing reticence to call out C and C-descended languages:</p> <blockquote> <p>Unlike other programming languages, Swift does not require you to create separate interface and implementation files for custom classes and structures.</p> </blockquote> <p>Because there’s such a long list of languages not directly descended from C which do that, right? 😉</p></li> <li><p>Rust differs not only from Swift but from every other modern language I have used in not having a constructor <em>syntax</em> for its instantiations. Whereas C++ has <code>new NameOfType()</code> and Python and Swift both have <code>NameOfType()</code>, “constructors” for Rust <code>struct</code>s are just functions which return an instance constructed using literal syntax, by convention <code>NameOfType::new()</code>.</p></li> <li><p>Let’s make a <code>struct</code> defining a location in a plane, you might do this in Swift (leaving aside initializer values; I’ll come back to those later). These definitions look <em>very</em> similar. Swift:</p> <pre class="swift"><code>struct Point { var x: Double var y: Double }</code></pre> <p>Rust:</p> <pre class="rust"><code>struct Point { x: f64, y: f64, }</code></pre></li> <li><p>Creating the types looks a little different, though. Here’s a constructor in Swift:</p> <pre class="swift"><code>let point = Point(x: 0, y: 0)</code></pre> <p>And the two ways we could construct the type in Rust, a literal constructor (fairly similar to constructing <code>dict</code> literals in Python or object literals in JavaScript):</p> <pre class="rust"><code>let point = Point { x: 0.0, y: 0.0 };</code></pre> <p>Or a constructor method, <code>new</code>:</p> <pre class="rust"><code>// &quot;Constructor&quot; impl Point { fn new(x: f64, y: f64) -&gt; Point { Point { x: x, y: y } } } let another_point = Point::new(0, 0);</code></pre> <p>Observe: these two things in Rust are the same under the covers (though if <code>Point</code>s had non-public internals, they would be non-trivially different: you couldn’t construct it with its private members externally). As usual, Rust opts to keep the language relatively small in these core areas. Given the plethora of ways you can construct something in e.g. C++, I count that a big win.</p></li> <li><p>Another difference: Swift has <em>syntax</em> for default values; Rust uses a <code>trait</code> instead. In Swift, you simply supply the default value in the definition of the <code>struct</code> or <code>class</code>:</p> <pre class="swift"><code>struct Point { var x = 0.0 var y = 0.0 } let point = Point()</code></pre> <p>In Rust, you use <code>std::default::Default</code>, which provides a standard value for a given type, and for simple types can be supplied by the compiler even for custom types. Here is the equivalent Rust code:</p> <pre class="rust"><code>use std::default::Default; #[derive(Default)] struct Point { x: f64, y: f64, } let point = Point::default();</code></pre> <p>This is reasonable enough, but we can also supply our own custom implementation if we so desire:</p> <pre class="rust"><code>use std::default::Default; struct Point { x: f64, y: f64, } impl Default for Point { fn default() -&gt; Point { Point { x: 0.0, y: 0.0 } } } let point = Point::default();</code></pre> <p>Of course, this is trivial for this type, but you can see how it could be useful for more complex types.</p></li> <li><p>The tradeoffs here are our usual suspects: Rust’s re-use of an existing concept/tool within the language (<code>trait</code>) vs. Swift’s use of syntax. Rust is slightly more explicit, making it obvious that a default value is being created—but Swift is perfectly readable and the syntax is consistent with many other languages, and it <em>is</em> shorter.</p></li> <li><p>Both languages use <code>.</code> syntax for member access. Swift:</p> <pre class="swift"><code>println(&quot;The point is: \(point.x), \(point.y)&quot;)</code></pre> <p>Rust:</p> <pre class="rust"><code>println!(&quot;The point is {:}, {:}&quot;, point.x, point.y);</code></pre></li> <li><p>Swift lets you define items <em>within</em> a struct as mutable or constant. So you can create a variable struct instance, with some of its items immutable:</p> <pre class="swift"><code>struct PointOnZAxis { var x: Double var y: Double let z = 0.0 } var point = PointOnZAxis(x: 4.0, 5.0) point.x = 5.0 point.y = 6.0 // This wouldn&#39;t compile, though: // point.z = 1.0</code></pre> <p>This is pretty handy for a lot of object-oriented programming approaches.</p></li> <li><p>And Rust doesn’t have it. There are ways to accomplish the same thing; this isn’t the end of the world. Still, it’s an interesting omission, and it’s very much by design. Rust <em>used</em> to have this feature, and dropped it—and for good reason. Say you had a mutable field in a mutable struct, and then an immutable reference to it; should the mutable field be mutable, or immutable, with that reference?</p></li> <li><p>The Rusty way to do this is to differentiate between public and private data. The above examples don’t make the public/private distinction particularly clear, because they assume everything is within the same module. However, many times, this will not be the case.</p> <pre class="rust"><code>mod geometry { pub struct Point { x: f64, pub y: f64, } impl Point { pub fn new() -&gt; Point { Point { x: 0.0, y: 0.0 } } pub fn set_x(&amp;mut self, x: f64) { self.x = x; } } } fn main() { // Won&#39;t compile: the `x` field is private. // let mut p = geometry::Point { x: 0.0, y: 0.0 }; // Will compile: the `new` method is public. let mut p = geometry::Point::new(); // Won&#39;t compile: `x` isn&#39;t public. // p.x = 4.0; // You can use the setter, though: p.set_x(4.0); // You *can* set `y` directly, though, because it&#39;s public. p.y = 14.0; // You can&#39;t set fields either way if the instance is immutable. let q = geometry::Point::new(); // This fails because `set_x` requires a mutable reference, but `q` is // immutable. // q.set_x(4.0); // This fails because `q` is immutable, and so all its fields are, too. // q.y = 14.0; }</code></pre></li> <li><p>This is an interesting way of handling this issue. Rust takes the fairly standard use of information hiding (one of the basic principles of most object-oriented programming techniques) and combines it with the language’s normal mutability rules to make it so that the mutability of any given instance data is quite clear: all public members are just as mutable as the struct. If a member isn’t potentially publicly mutable, it isn’t publicly accessible. I really like this, though it took some mental readjustment.</p></li> <li><p>There’s one other difference here, and it’s actually one of the areas Swift and Rust diverge substantially. Rust has <code>struct</code> for all product types; Swift splits them into <code>struct</code> types and <code>class</code> types.</p></li> <li><p>Swift <code>class</code>es have inheritance; there is presently <em>no</em> inheritance in Rust.</p></li> <li><p>Additionally, whereas Rust determines whether to use pass-by-reference or-value depending on details of the type (whether it implements the <code>Copy</code> <code>trait</code>) and expected arguments to a function, Swift makes that distinction between <code>class</code> (pass-by-reference) and <code>struct</code> (pass-by-value) types. Quirky.</p></li> <li><p>Not bad, <em>per se</em>. But quirky.</p> <p><strong>Edit:</strong> I recently bumped into some discussion of data types in C♯ along with C, C++, and Java (<a href="http://joeduffyblog.com/2015/12/19/safe-native-code/">here</a>) and discovered that Swift is stealing this idea from C♯, which <a href="https://msdn.microsoft.com/en-us/library/0taef578.aspx">makes the same copy/reference distinction</a> between <code>struct</code> and <code>class</code>.</p></li> <li><p>One consequence of this: in Rust, you’re always rather explicit about whether you’re accessing things by value vs. by reference. Not so in Swift; you have to remember whether the item you’re touching is a <code>struct</code> type or a <code>class</code> type, so that you can <em>remember</em> whether a given assignment or function call results in a reference or a copy. This is necessary because Swift doesn’t let you make that explicit (trying to hide the memory management from you). And it’s not alone in that, of course; many other high-level languages obscure that for convenience but still require you to think about it in certain circumstances. I’ve been bitten in the past by the value/reference distinction when thinking through the behavior of Python objects, for example, so that’s not a critique of Swift. Moreover, having the distinction between <code>struct</code> and <code>class</code> types does let you be <em>more</em> explicit than you might in e.g. Python about how given data will be handled.</p></li> <li><p>I won’t lie, though: I like Rust’s approach better. (Shocking, I know.)</p></li> <li><p>All that nice initializer syntax for Swift <code>struct</code> types is absent for its <code>class</code> types, which seems strange to me.</p></li> <li><p>Swift supplies some syntax for object identity, since it’s useful to know not only whether two <code>class</code> instances have the same data, but are in fact the same instance. You can use <code>===</code> and <code>!==</code>. Handy enough. To get at this kind of equivalence in Rust, you have to use raw pointers (which are often but not always <code>unsafe</code>; you can do this specific comparison <em>without</em> being <code>unsafe</code>, for example) to check whether the memory addresses are the same.</p></li> </ul> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-ix.html"><strong>Previous:</strong> Sum types (<code>enum</code>s) and more on pattern matching.</a></li> <li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xi.html"><strong>Next:</strong> Hopes for the next generation of systems programming.</a></li> </ul> Chris KrychoSun, 06 Dec 2015 11:25:00 -0500tag:v4.chriskrycho.com,2015-12-06:/2015/rust-and-swift-x.htmllisticlessoftware developmentrustswiftrust-and-swiftRust and Swift (ix)http://v4.chriskrycho.com/2015/rust-and-swift-ix.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <ul> <li><p>Right off the bat when looking at the definitions for Swift’s and Rust’s <code>enum</code> types, a difference pops out: the use of the keyword <code>case</code> to introduce an enum member in Swift. In one sense, this overloads that keyword, but in another sense it’s fine: pattern matching and enums go hand in hand, so the use in both cases is fairly natural. Rust doesn’t have any special syntax to designate the elements of an enum; they’re just separated by commas.</p></li> <li><p>I am not at all shocked to find that Swift has a variant syntax for its unit type case declarations, where a single <code>case</code> keyword precedes a list of comma-separated cases defined on a single line. (At this point, I would be more surprised <em>not</em> to find a variant syntax for something in Swift!)</p></li> <li><p>Something truly wonderful about both Rust and Swift: enumerated types aren’t just wrappers around integer values. They’re real types of their own. This is powerful.</p></li> <li><p>Rust and Swift also share in having enumerated types that can hold values. The most prominent of these so far in the Swift book are optionals, the <code>Optional</code> enum type, corresponding very closely to Rust’s <code>Option</code> type. Having had these for a bit in playing with Rust, and having gotten familiar with the utility of types like these while reading <a href="https://gumroad.com/l/maybe-haskell"><em>Maybe Haskell</em></a>—a delightful book which introduces Haskell and functional programming using Haskell’s <code>Maybe</code> type—I now miss them profoundly in languages which don’t have them. (Which is to say: every language I use on a regular basis professionally: C, C++, Python, JavaScript, etc.).</p></li> <li><p>Swift’s enum types don’t have integer values <em>by default</em>—but they can have them if you define a type and assign a value to each enum case at the definition. These “raw values” are distinct from the “associated values” noted just above. I expect these exist primarily for ease of interoperation with Objective-C.</p></li> <li><p><del>Rust doesn’t have anything like this, at least that I can think of. The main place it would be useful would be for foreign function interfaces (as in Swift), and this is one of several such gaps in Rust,</del> along with the lack of a straightforward way to map to C’s <code>union</code> types. <del>There are trade offs in terms of adding the functionality to the language, though, as it substantially increases the complexity of what an enum value can be, I think.</del></p> <p><strong>Edit:</strong> This was incorrect. From the <a href="https://doc.rust-lang.org/reference.html">Rust Reference</a> section on <a href="https://doc.rust-lang.org/reference.html#enumerations">Enumerations</a>:</p> <blockquote> <p>Enums have a discriminant. You can assign them explicitly:</p> <pre class="rust"><code>enum Foo { Bar = 123, }</code></pre> <p>If a discriminant isn’t assigned, they start at zero, and add one for each variant, in order.</p> <p>You can cast an enum to get this value:</p> <pre class="rust"><code>let x = Foo::Bar as u32; // x is now 123u32</code></pre> <p>This only works as long as none of the variants have data attached. If it were <code>Bar(i32)</code>, this is disallowed.</p> </blockquote></li> <li><p>Initialization of Swift’s raw-valued enum type is quite similar, and pleasantly so, to Python’s initialization of enums.</p></li> <li><p>In a surprising change from the usual, Swift’s syntax for binding variable names when pattern matching against an enum is <em>more</em> verbose than Rust’s, requiring the use of either a leading <code>let</code> on the <code>case</code> statement if all the elements are of the same type, or a <code>let</code> in front of each element otherwise:</p> <pre class="swift"><code>var matchedValue: String let matchee = 3.14159 switch matchee { case 3.14159: matchedValue = &quot;pi&quot; case _: matchedValue = &quot;not pi&quot; }</code></pre> <p>In Rust, a matched pattern can simply bind its value directly:</p> <pre class="rust"><code>let matchee = 3.14159; let matchedValue = match matchee { 3.14159 =&gt; &quot;pi&quot;.to_string(), _ =&gt; &quot;not pi&quot;.to_string() };</code></pre></li> <li><p>Swift has the ability to do recursive enumerations with its <code>indirect</code> type. This is conceptually interesting, but off the top of my head I can’t think of a time when this would have been useful at any point since I started programming seven and a half years ago. The book’s example of a recursive function aliasing arithmetic expressions is fine, but not particularly illuminating to me. I suspect, though, that it might make more sense if I were more familiar with pure functional programming paradigms.</p> <p><strong>Edit:</strong> a friend <a href="https://alpha.app.net/jws/post/65990633">points out</a>:</p> <blockquote> <p>Indirect enums are useful for recursive types in general. There are a lot of these: Lists, trees, and streams are the big ones that come to mind.</p> </blockquote></li> <li><p>All those same lines: Rust does <em>not</em> have the ability to have recursive enumerations at present (or recursive <code>struct</code> types, for that matter), at least without heap-allocating with <code>Box</code> along the way. You <em>can</em> construct such a type, in other words, but you have to be explicit about how you’re handling the memory, and it can’t be stack-allocated.</p> <ul> <li><p>For an example of a recursive enumeration type (as well as an interesting/hilarious example of how you can easily confuse the compiler if you do this wrong), see <a href="https://users.rust-lang.org/t/recursive-enum-types/2938">this Rust forum post</a>.</p></li> <li><p>For some discussion on stack- and heap-allocated memory in Rust, I’ll shamelessly promote my Rust podcast, <a href="http://www.newrustacean.com">New Rustacean</a>: take a listen to <a href="http://www.newrustacean.com/show_notes/e005/index.html">e005: Allocate it where?</a></p></li> </ul></li> </ul> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-viii.html"><strong>Previous:</strong> Functions, closures, and an awful lot of Swift syntax.</a></li> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-x.html"><strong>Next:</strong> Classes and structs (product types), and reference and value types.</a></li> </ul> Chris KrychoMon, 09 Nov 2015 22:20:00 -0500tag:v4.chriskrycho.com,2015-11-09:/2015/rust-and-swift-ix.htmlsoftware developmentlisticlesrustswiftrust-and-swiftRust and Swift (viii)http://v4.chriskrycho.com/2015/rust-and-swift-viii.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <ul> <li><p>Rust and Swift handle function definition fairly similarly, at least for basic function definitions. In fact, for most basic functions, the only difference between the two is the keyword used to indicate that you’re declaring a function: <code>fn</code> in Rust and <code>func</code> in Swift.</p></li> <li><p>Likewise, both return an empty tuple, <code>()</code>, called the <em>unit type</em> in Rust or <code>Void</code> in Swift. Note, however, that this unit/<code>Void</code> type is <em>not</em> like C(++)’s <code>void</code> or Java’s <code>null</code>: you cannot coerce other types to it; it really is an empty tuple.</p></li> <li><p>Type declarations on functions are basically identical for simple cases, though they vary into the details as you get into generics and constraints in generics.</p></li> <li><p>I have no idea why the Swift team chooses to represent function names like this: <code>function_name(_:second_param:third_param:&lt;etc.&gt;)</code>. Perhaps it’s a convention from other languages I’m simply unfamiliar with, but it seems both odd and unhelpful: eliding the first parameter name obscures important information. Also, why use colons for the delimiter?</p> <p><strong>Edit:</strong> I’m informed via Twitter and App.net that this reflects how function names work in Objective C, and derives ultimately from Smalltalk.</p></li> <li><p>Being able to name the items in a returned type in Swift is quite handy; it’s something I have often wanted and had to work around with dictionaries or other similar types in Python.</p></li> <li><p>We’ll see how I feel once I’ve been writing both for a while, but initially I <em>strongly</em> prefer Rust’s more-obvious (if also somewhat longer) <code>-&gt; Option&lt;i32&gt;</code> to return an optional integer to Swift’s <code>-&gt; Int?</code>. I am quite confident that I’ll miss that trailing <code>?</code> somewhere along the way.</p></li> <li><p>I’m sure there’s a reason for Swift’s internal and external parameter names and the rules about using <code>_</code> to elide the need to use keyword arguments (but automatically eliding the first one) and so on… but I really can’t see the utility, overall. It seems like it would be better just to have Python-like args and keyword args.</p></li> <li><p>That’s doubly so given that Swift’s rules for default-valued parameters map exactly to Python’s: they need to go at the end, after any parameters which don’t have default values.</p></li> <li><p>Swift’s variadic parameters are nice—though of course limited, since if you have more than one, the compiler may not know how to resolve which destination parameter a given argument belongs with. (I imagine the compiler <em>could</em> be extended to be able to handle multiple variadic parameters as long as they were all of different types, but that’s probably not worth the work or the potential confusion it would introduce.) In any case, it’s a small nicety that I do wish Rust had.</p></li> <li><p>Swift’s variable parameters are… interesting. I can see the utility, sort of, but (probably from years of habit with C and Python and pass-by-reference types), it’s just not a pattern that makes a lot of sense to me right now. No doubt I’ll get used to them in idiomatic Swift, but while Rust doesn’t have a similar feature, I suspect I won’t miss it.</p></li> <li><p>In/out parameters—that is, mutable pass-by-reference types—are available in both languages. The syntax is <em>very</em> different here, as are the semantics.</p> <p>Swift has the <code>inout</code> keyword, supplied before a parameter definition:</p> <pre class="swift"><code>func adds4ToInput(inout num: Int) { num += 4; }</code></pre> <p>Rust has instead a variation on every other type definition, declaring the type in this case to be a mutable reference:</p> <pre class="rust"><code>fn adds_4_to_input(num: &amp;mut i32) { num += 4; }</code></pre> <p>As usual, in other words, Swift opts to use new syntax (in this case, a dedicated keyword) while Rust opts to use the same syntax used everywhere else to denote a mutable reference. In fairness to Swift, though, this is something of a necessity there. From what I’ve seen so far, Swift generally doesn’t (and perhaps can’t?) do pointers or references explicitly (though of course it’s handling lots of things that way under the covers); arguments to functions are a special case, presumably present primarily for interoperability with Objective-C.</p></li> <li><p>Swift’s function type definitions, as used in e.g. function parameter definitions, are quite nice, and reminiscent of Haskell in the best way. Rust’s are pretty similar, and add in its <code>trait</code> usage—because functions types <em>are</em> <code>trait</code>s. Once again, I really appreciate how Rust builds more complicated pieces of functionality on lower-level constructs in the language. (Swift may be doing similar under the covers, but the Swift book doesn’t say.)</p></li> <li><p>Again, though, the downside to Rust’s sophistication is that it sometimes bundles in some complexity. Returning a function in Swift is incredibly straightforward:</p> <pre class="swift"><code>func getDoubler() -&gt; (Int) -&gt; Int { func doubler(number: Int) -&gt; Int { return number * 2 } return doubler } func main() { let doubler = getDoubler() println(&quot;\(doubler(14))&quot;) // -&gt; 28 }</code></pre> <p>Doing the same in Rust is a bit harder, because—as of the 1.3 stable/1.5 nightly timeframe—it requires you to explicitly heap-allocate the function. Swift just takes care of this for you.</p> <pre class="rust"><code>fn get_doubler() -&gt; Box&lt;Fn(i32) -&gt; i32&gt; { fn doubler(number: i32) -&gt; i32 { number * 2 } Box::new(doubler) } fn main() { let doubler = get_doubler(); println!(&quot;{:}&quot;, doubler(14)); // -&gt; 28 }</code></pre> <p>If you understand what’s going on under the covers here, this makes sense: Rust normally stack-allocates a function in a scope, and therefore the <code>doubler</code> function goes out of scope entirely when the <code>get_doubler</code> function returns if you don’t heap-allocate it with <code>Box::new</code>.</p></li> <li><p>In both languages, closures and “ordinary” functions are variations on the same underlying functionality (as it should be). In Rust’s case, functions and closures both implement the <code>Fn</code> trait. In Swift’s case, named functions are a special case of closures.</p></li> <li><p>The Swift syntax for a closure is, well, a bit odd to my eye. The basic form is like this (with the same “doubler” functionality as above):</p> <pre class="swift"><code>{ (n: Int) -&gt; Int in return n * 2 }</code></pre> <p>For brevity, this can collapse down to the shorter form with types inferred from context, parentheses dropped and the <code>return</code> keyword inferred from the fact that the closure has only a single expression (note that this wouldn’t be valid unless in a context where the type of <code>n</code> could be inferred):</p> <pre class="swift"><code>{ n in n * 2 }</code></pre> <p>The simplicity here is nice, reminiscent in a good way of closures/lambdas in other languages.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> The fact that it’s a special case is less to my taste.</p></li> <li><p>Rust’s closure syntax is fairly similar to Swift’s brief syntax. More importantly, there’s no special handling for closures’ final expressions. Remember: the final expression of <em>any</em> block is always returned in Rust.</p> <pre class="rust"><code>|n| n * 2</code></pre> <p>If we wanted to fully annotate the types, as in the first Swift example, it would be like so:</p> <pre class="rust"><code>|n: i32| -&gt; i32 { n * 2 }</code></pre></li> <li><p>There are even <em>more</em> differences between the two, because of Rust’s ownership notion and the associated need to think about whether a given closure is being borrowed or moved (if the latter, explicitly using the <code>move</code> keyword).</p></li> <li><p>Swift has the notion of shorthand argument names for use with closures.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> The arguments to a closure get the default names <code>$0</code>, <code>$1</code>, etc. This gets you even <em>more</em> brevity, and is quite convenient in cases where closures get used a lot (<code>map</code>, <code>sort</code>, <code>fold</code>, <code>reduce</code>, etc.).</p> <pre class="swift"><code>{ $0 * 2 }</code></pre></li> <li><p>If that weren’t enough, Swift will go so far as to simply reuse operators (which are special syntax for functions) as closures. So a closure call could simply be <code>+</code> for a function expecting a closure operating on two numbers; Swift will infer that it needs to map back to the relevant method definition on the appropriate type.</p></li> <li><p>The upside to this is that the code can be incredibly brief, and—once you’re used to it, at least—still fairly clear. The downside to this is yet <em>more</em> syntax for Swift, and the ever-growing list of things to remember and ways to write the same thing I expect will lead to quite a bit of instability as the community sorts out some expectations for what is idiomatic in any given instance.</p></li> <li><p>And if that weren’t enough, there is more than one way to supply the body of a closure to a Swift function that expects it: you can supply a block (<code>{ /* closure body */ }</code>) <em>after</em> the function which expects it. Yes, this can end up looking nearly identical to the form for declaring a function:</p> <pre class="swift"><code>someFunctionExpectingAnIntegerClosure() { n * 2 }</code></pre> <p>But you can also drop the parentheses if that’s the only argument.</p> <pre class="swift"><code>someFunctionExpectingAnIntegerClosure { n * 2 }</code></pre></li> <li><p>In terms of the <em>mechanics</em> of closures, and not just the syntax, the one significant difference between Rust and Swift is the same one we’ve seen in general between the two languages: Swift handles the memory issues automatically; Rust makes you be explicit about ownership. That is, as noted above about the closures themselves, in Rust you may have to <code>move</code> ownership to get the expected behavior. Both behave basically like closures in any other language, though; nothing surprising here. Both also automatically copy values, rather than using references, whever it makes sense to do so.</p></li> <li><p>Swift autoclosures allow for lazy evaluation, which is neat, but: <em>yet more syntax</em>! Seriously. But I think all its other closure syntaxes <em>also</em> allow for lazy evaluation. The only reason I can see to have the special attribute (<code>@autoclosure</code>) here is because they added this syntax. And this syntax exists so that you can call functions which take closures as if they <em>don’t</em> take closures, but rather the argument the closure itself takes. But of course, this leads the Swift book to include the following warning:</p> <blockquote> <p><strong>Note:</strong> Overusing autoclosures can make your code hard to understand. The context and function name should make it clear that the evaluation is being deferred.</p> </blockquote> <p>Yes, care needed indeed. (Or, perhaps, you could just avoid adding more special syntax that leads to unexpected behaviors?)</p></li> <li><p>Good grief. I’m tired now. That’s a half-dozen variants on <em>closure syntax</em> in Swift.</p></li> <li><p>Remember: there’s still just one way to write and use a closure in Rust.</p></li> <li><p>This takes me back to something I noticed <a href="/2015/rust-and-swift-ii.html">early on</a> in my analysis of the two languages. In Swift, there’s nearly always more than one way to do things. In Rust, there’s usually one way to do things. Swift prefers brevity. Rust prefers to be explicit. In other words, Swift borrows more of its philosophy from Perl; Rust more from Python.</p></li> <li><p>I’m a Python guy, through and through. Perl drives me crazy every time I try to learn it. You could guess (even if you hadn’t already seen) where this lands me between Rust and Swift.</p></li> </ul> <p>This post is incredibly long, but I blame that on the (frankly incredible) number of variants Swift has on the same concept.</p> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-vii.html"><strong>Previous:</strong> Pattern matching and the value of expression blocks.</a></li> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-ix.html"><strong>Next:</strong> Sum types (<code>enum</code>s) and more on pattern matching.</a></li> </ul> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>Compare the closure syntaxes especially in Ruby and ES6+.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> <li id="fn2" role="doc-endnote"><p>For a similar example in another up-and-coming language, see <a href="http://elixir-lang.org/getting-started/modules.html#function-capturing">Elixir</a>, which does almost exactly the same but with <code>&amp;</code> in place of <code>$</code>.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoSun, 18 Oct 2015 11:50:00 -0400tag:v4.chriskrycho.com,2015-10-18:/2015/rust-and-swift-viii.htmlsoftware developmentlisticlesrustswiftrust-and-swiftRust and Swift (vii)http://v4.chriskrycho.com/2015/rust-and-swift-vii.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past month. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <ul> <li><p>Both Rust and Swift have <em>pattern-matching</em>, and with what appears to be fairly similar basic behavior. (I touched on this briefly in my <a href="/2015/rust-and-swift-i.html">first post in the series</a>.) In Rust this goes under the <code>match</code> construct, with matches specified like <code>&lt;pattern&gt; =&gt; &lt;expression|statement&gt;</code>, optionally with guards specified with <code>if</code> expressions. In Swift, patterns are matched using the <code>switch</code> construct, with matches specified like <code>case &lt;pattern&gt;: &lt;expression|statement&gt;</code>, optionally with guards specified with <code>where</code> expressions. (<code>where</code> is also used in Rust, but for generic constraints, not pattern match guards.)</p></li> <li><p>Both languages allow you to bind names to a matched pattern: Swift with <code>case let &lt;name&gt;</code> and Rust simply by using the name in a normal destructuring expression as part of the match definition.</p> <p><strong>Edit:</strong> that’s not <em>quite</em> right. In Rust, you use the <code>@</code> operator with the variable name you want to bind in the match.</p> <p><strong>Edit the second:</strong> I was mixed up, because Rust actually has <em>both</em> of those options. You can either match directly, e.g. when getting the value of an <code>Option</code> type: <code>Some(value)</code> as the pattern will bind <code>value</code>. But if you need to bind a specific part of more complicated data structure, the <code>@</code> operator is present to let you do it in a fairly straightforward way.</p></li> <li><p>Both languages allow for the use of <code>_</code> as a “wildcard” in match definitions. Since match definitions in Rust use the patterns directly, the equivalent of Swift’s C-like <code>default</code> is simply a wildcard match pattern (<code>_ =&gt; &lt;-expression|statement&gt;</code>).</p></li> <li><p>One significant difference: like its <code>if</code> blocks, Rust’s <code>match</code> blocks are expressions, so they can be assigned. I.e., you can write this:</p> <pre class="rust"><code>let test = 5u32; let description = match test { 0..10 =&gt; &quot;less than ten&quot;, _ =&gt; &quot;greater than ten&quot;, } println!(&quot;{?:}&quot;); // &quot;less than ten&quot;</code></pre> <p>Swift doesn’t let you do this; the same thing there would be written like this:</p> <pre class="swift"><code>let test: UInt32 = 5 var description: String switch test { case 0..&lt;10: description = &quot;less than ten&quot; default: description = &quot;greater than ten&quot; } println(&quot;\(description)&quot;)</code></pre></li> <li><p>Both languages have <code>break</code> statements, but in Rust they’re only used in loop constructs, while Swift (like C) uses them to escape <code>case</code>s as well. The Swift book gives an example of one place they’re necessary in a <code>switch</code>: to match a case and do nothing there (e.g. <code>default: break</code>). In Rust, you would simply supply an empty block for that scenario (e.g. <code>_ =&gt; {}</code>).</p></li> <li><p>Correctly, both languages force you to match exhaustively on relevant patterns. If you’re matching an enumerated type, for example, you must handle every enumerated value. You can of course do this with wildcard patterns or with Swift’s <code>default</code>, but the good thing is that both languages will refuse even to compile if a given pattern isn’t matched.</p></li> <li><p>Swift’s default behavior around its <code>switch</code> statements is sane: it does <em>not</em> automatically fall through into the next statement. It does let you do this, without checking the condition on the next statement (as in C), using the <code>fallthrough</code> keyword. Rust, by contrast, simply doesn’t allow this at all.</p></li> <li><p>Both languages supply named control statements (loops, etc.), with slightly different syntax for naming them. Rust’s, curiously, shares its syntax with lifetime definitions—more on those in a future post.</p></li> <li><p>I don’t believe Rust has anything quite like Swift’s <code>guard</code>s, which allow you to leave normal or expected control flow in the main body of a block, with a secondary block for cases where the <code>guard</code> isn’t matched. This isn’t a huge deal, but it does fit as a nice convenience into the typical <code>if let</code> pattern in Swift. Basically, it just lets you elide an empty <code>if</code> block and supply only the <code>else</code> block.</p> <p><strong>Edit:</strong> a friend <a href="https://alpha.app.net/jws/post/64804111">points out</a> that Swift <code>guard</code>s also require you to exit the current scope, so it’s unambiguous what you’re doing if you use them.</p></li> </ul> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-vi.html"><strong>Previous:</strong> Collection types and the difference between syntax and semantics.</a></li> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-viii.html"><strong>Next:</strong> Functions, closures, and an awful lot of Swift syntax.</a></li> </ul> Chris KrychoSat, 19 Sep 2015 15:00:00 -0400tag:v4.chriskrycho.com,2015-09-19:/2015/rust-and-swift-vii.htmlsoftware developmentlisticlesrustswiftrust-and-swiftRust and Swift (vi)http://v4.chriskrycho.com/2015/rust-and-swift-vi.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past month. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <p>It kind of feels like this summarizes a <em>lot</em> of things about the overall design of Swift:</p> <blockquote> <p>Although the two forms are functionally identical, the shorthand form is preferred and is used throughout this guide when referring to the type of an array. —<em>The Swift Programming Language (Swift 2 Prerelease)</em></p> </blockquote> <p>The documentation for the various types in Rust’s <code>std::collections</code> module is hilarious and great. Highly recommended.</p> <p>One thing that jumped out at me reading this chapter of the Swift book (though I don’t think it’s been explicitly discussed yet): Rust doesn’t have named parameters; Swift does. There are good reasons for that in both cases, but I suspect this is one of the small details I’ll miss the most in Rust. I’ve been spoiled by Python.</p> <p>Swift’s <code>Array</code> type is analogous to Rust’s <code>Vec</code> type (usually created with the <code>vec!</code> macro), <em>not</em> its <code>Array</code> type. Rust <code>Vec</code>s and Swift <code>Array</code>s are dynamically sized and created on the heap, whereas Rust’s <code>Array</code>s are statically sized and created on the stack. Syntax for creating <code>Array</code>s in both languages is quite similar (though the results are different):</p> <ul> <li>Swift: <ul> <li>Fixed size: <code>let an_array: [Int] = [1, 2, 3]</code></li> <li>Variable size: <code>var an_array = [1, 2, 3]</code></li> </ul></li> <li>Rust: <ul> <li>Array: <code>let an_array: [i32, 3] = [1, 2, 3];</code></li> <li>Vector: <code>let a_vector: Vec&lt;i32&gt; = vec![1, 2, 3];</code></li> </ul></li> </ul> <p>That’s the long form, of course; both languages have type inference, so you’d rarely write it like that. The usual form would be with the type in all of those cases:</p> <ul> <li>Swift: <ul> <li>Fixed size: <code>let an_array = [1, 2, 3]</code></li> <li>Variable size: <code>var an_array = [1, 2, 3]</code></li> </ul></li> <li>Rust: <ul> <li>Array: <code>let an_array = [1, 2, 3];</code></li> <li>Vector: <code>let a_vector = vec![1, 2, 3];</code></li> </ul></li> </ul> <p>Rust also adds the concept of “slices,” which provide access to segments of arrays, and are heap-allocated as pointers to a given item in the array and a length (number of elements) included.</p> <p><code>Array</code> operations in Swift are all pretty reasonable, and surprisingly descriptive. They remind me in a good way of Python’s <code>list</code> methods.</p> <p>There are a <em>lot</em> of <a href="http://doc.rust-lang.org/stable/std/vec/struct.Vec.html">ways to interact with <code>Vec</code>s in Rust</a>. (That’s not a bad thing.) A bit surprising to me was the absence of an <code>enumerate</code> method, on <code>Vec</code> itself, but then I discovered that it exists in the <code>IntoIter</code> struct in the same module, which fully implements the <code>Iterator</code> <code>trait</code>. As a result, it has an <code>enumerate</code> function returning an <code>Enumerate</code> <code>struct</code> instance. (Under the covers, I suspect Swift <code>Array</code>s just implement an <code>Iterable</code> <code>protocol</code>, which is similar to this approach in some ways.)</p> <p>This makes a point I’m coming back to fairly often: Rust doesn’t necessarily put everything on a single object definition, but rather into a set of related <code>struct</code> or <code>enum</code> types and <code>trait</code>s. This is really powerful, but it’s going to take some mental adjustment. In this way, Swift’s structure and semantics are much more like the languages I’m used to than Rust’s are (but even there, the use of <code>protocols</code> gives it considerable new flexibility).</p> <p>Note that I said <em>semantics</em>, not syntax. Swift and Rust are a great example of how very similar syntax can mask differences in semantics. (For another such example, compare JavaScript’s syntax and semantics to Java’s: they’re superficially similar syntactically, and light years apart semantically.)</p> <p>Swift’s <code>Set</code> type and Rust’s roughly analogous <code>HashSet</code> both have a <code>contains</code> method which behaves much like Python’s <code>in</code> keyword. Indeed, and perhaps unsurprisingly, the two types implement many of the same methods in general. This is perhaps to be expected given that the language around sets (as a mathematical concept being mapped down into a representation in a program) is quite standardized.</p> <p>Because of their stricter typing systems, both Rust and Swift require you to specify the types used in their mapping constructs (Rust has <code>HashMap</code> and Swift has <code>Dictionary</code>), though of course both can infer this as well in certain cases. At the most basic level, you can’t use arbitrary (hashable) types as keys in mixed fashion like you can in e.g. Python’s <code>dict</code> type, but in practice this shouldn’t matter, for two reasons:</p> <ol type="1"> <li>It’s generally inadvisable to use different types for keys in the same dictionary anyway. To me, at least, that usually indicates the need to step back and think more carefully about the types and data structures I’m using.</li> <li>For the occasional case where it <em>is</em> appropriate, I wonder if you could declare the type as generic in either Rust or Swift. I’m putting this down as a TODO item for myself to find out!</li> </ol> <p>I really wish that Swift used the Python-style curly-brace delimited syntax (<code>{'key': 'value'}</code>) for its dictionary literal initializers. I can see, from a syntax reason, why it doesn’t: that would overload the block syntax (which Python can avoid because it’s white-space delimited). But it’s <em>really</em> convenient.</p> <p>Along similar lines, I can see why the Swift designers chose to make all iterables have literal initializers using braces (<code>[...]</code>); it makes parsing fairly straightforward. However, the result is that it’s pretty difficult to see at first glance what you’re dealing with. It could quite easily be an <code>Array</code>, a <code>Set</code>, or a <code>Dictionary</code>.</p> <p>This highlights a too-little-appreciated aspect of programming language design: <em>readability</em>. However much we programmers enjoy writing code, the reality is that we will all spend a great deal of our time—probably even a majority of it—reading it instead. Thus, while we should care about conveniences for writing code, and being overly verbose can be a pain, we should also concern ourselves with the ease of comprehending code when it is read, and the syntax and conventions a language embraces are a big part of this.</p> <p>The <code>Dictionary</code> type in Swift is a pretty close analog to Python’s <code>dict</code>, right down to several of the method names. the same is true of Rust’s <code>HashMap</code>. That’s not a bad thing by any stretch of the imagination.</p> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-v.html"><strong>Previous:</strong> The value (and challenge) of learning languages in parallel.</a></li> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-vii.html"><strong>Next:</strong> Pattern matching and the value of expression blocks.</a></li> </ul> Chris KrychoSat, 19 Sep 2015 09:00:00 -0400tag:v4.chriskrycho.com,2015-09-19:/2015/rust-and-swift-vi.htmlsoftware developmentrustswiftrust-and-swiftRust and Swift (v)http://v4.chriskrycho.com/2015/rust-and-swift-v.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past month. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <p>I’ve been working on learning Swift over the past couple weeks, and had spent the month prior to that doing a deep first dive on Rust. This kind of approach, learning two languages basically at the same time, is entirely new to me, and for good reason. Programming languages are not trivial to learn, and to learn them meaningfully one must practice with them a great deal.</p> <p>I’m doing this largely of necessity. I’m hoping to build an application with a very capable, performant cross-platform core language (Rust), but planning to ship a native OS X app (first) when all is said and done. My desire to make the core libraries portable rules out Swift immediately. To be frank, so does the fact that it’s an Apple language: I am happy to use Apple’s tools on its platform, but I don’t want to shackle myself to their choices in the long run. Too, having good Rust experience is likely to be valuable in many other contexts.</p> <p>So I need to learn both.</p> <p>And, while I wouldn’t ordinarily recommend this course of action—indeed, unless you already have a fair bit of programming experience and already know several languages, I’d actively recommend against it—I’m finding it enormously profitable. The languages have been designed in roughly the same time frame, cite many of the same influences, and overlap substantially in terms of audience and goals. Yet they are, as this series has already highlighted, quite different languages in many ways.</p> <p>Learning them in parallel is helping me see the trade-offs each one has made, and force me to think about <em>why</em> they differ in the ways they do. In particular, I think I have a much better idea what’s going on “under the covers” in each language and therefore know what to expect of them better. This, in turn, has dramatically deepened my grasp of the languages relative to the amount I’ve been looking at them, compared to previous language-learning efforts. (It also helps that I’ve already learned a number of languages, of course, and that I’ve been pushing my brain into the learning-programming-languages space via reading about Haskell, functional patterns in JavaScript, and so on this year.)</p> <p>I have a long way to go in both languages, of course. Reading on nights and weekends, and the little bit of playing I’ve been able to do with each of them, is no replacement for just sinking my teeth into a project and finding the pain points. Nonetheless, I’m really glad to be learning these two languages <em>together</em>. If you’re up for a challenge, try it sometime! You’ll be surprised how much you learn.</p> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-iv.html"><strong>Previous:</strong> Language design tradeoffs, highlighted by string manipulation.</a></li> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-vi.html"><strong>Next:</strong> Collection types and the difference between syntax and semantics.</a></li> </ul> Chris KrychoSat, 12 Sep 2015 13:45:00 -0400tag:v4.chriskrycho.com,2015-09-12:/2015/rust-and-swift-v.htmlsoftware developmentrustswiftrust-and-swiftprogramming languagesIf-expressions in Rusthttp://v4.chriskrycho.com/2015/if-expressions-in-rust.html<p>I love the fact that all <code>if</code> statements in Rust are expressions. It gives you a great deal of expressitivity in the language.</p> <p>Let’s contrast with Python (which I love, for the record). In Python, you can do something like this:</p> <pre class="python"><code>some_condition = True if some_condition: a_value = &quot;Yeah!&quot; else: a_value = &quot;Oh, sads.&quot;</code></pre> <p>Those are <em>statements</em> in the body of the <code>if</code>/<code>else</code> block; you can’t assign the block itself to <code>a_value</code>. However, like C, C++, Java, etc., Python does provide an <em>expression</em>-type conditional, a ternary expression.</p> <p>So you can also do this:</p> <pre class="python"><code>some_condition = True a_value = &quot;Yeah&quot; if some_condition else &quot;Oh, sads.&quot;</code></pre> <p>This expression form of the <code>if</code> block is what all Rust <code>if</code> blocks are. So in Rust, the normal long form is:</p> <pre class="rust"><code>let some_condition = true; let a_value = if some_condition { &quot;Yeah!&quot; } else { &quot;Oh, sads.&quot; }</code></pre> <p>(You could also write this with a <code>let mut a_value</code> and then set its value inside the conditional blocks, but that’s not at all good form in Rust.)</p> <p>And of course, you can shorten that rather nicely where the expressions are brief enough:</p> <pre class="rust"><code>let some_condition = true; let a_value = if some_condition { &quot;Yeah!&quot; } else { &quot;Oh, sads.&quot; }</code></pre> <p>But this gets really nice when you have more complicated work to do in a Rust conditional. It doesn’t matter how many things going on inside an <code>if</code> expression; it’s still an expression. As such, you can also write this:<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p> <pre class="rust"><code>let some_condition = true; let a_value = if some_condition { let the_answer = 42; let theme = &quot;Take my love, take my land...&quot;; &quot;Yeah!&quot; // An expression! } else { let the_question = &quot;What do you get when you multiply six by nine?&quot;; let song = &quot;You can&#39;t take the sky from me!&quot;; &quot;Oh, sads.&quot; // An expression! }</code></pre> <p>Obviously this is totally contrived and silly; the point is that no matter what the internals are, <code>if</code> blocks are expressions, and their final expressions can be assigned like any other.</p> <hr /> <p>As a note: I got here because I was originally thinking you couldn’t do a one-liner like you can in Python. As shown above, that’s totally false, and in fact the Rust version is much more capable than Python’s, because you don’t need a dedicated ternary when all <code>if</code> blocks are expressions. Rust used to have a C-style ternary (<code>&lt;condition&gt; ? &lt;value if true&gt; : &lt;value if false&gt;</code>) but it was <a href="https://github.com/rust-lang/rust/issues/1698">removed</a> during the lead-up to the 1.0 release—a decision I wholeheartedly affirm.</p> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>Note that under normal conditions the compiler won’t actually accept this because of the unused names.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoSat, 12 Sep 2015 11:05:00 -0400tag:v4.chriskrycho.com,2015-09-12:/2015/if-expressions-in-rust.htmlsoftware developmentprogramming languagesrustpythonRust and Swift (iv)http://v4.chriskrycho.com/2015/rust-and-swift-iv.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past month. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <p>Both Swift and Rust directly address the issue of having to worry about memory allocation and safety. They do it in different ways, though: Swift by automatic reference counting, Rust by its concept of ownership. For a lot of day-to-day development, I can see the Swift approach being a win for the same reason a language like Python or Ruby is: having that all handled for you is <em>nice</em>. Having the power Rust gives you comes at the price of increased cognitive load from having to reason about ownership.</p> <p>To put it another way: all programming languages have to make trade-offs. Although I like Rust’s better than Swift’s so far, I’ve no doubt I will find any number of things to appreciate about Swift over Rust. You can’t have everything.</p> <p>This caught my attention in part because dealing with things like strings (or other pass-by-value types) in Swift is rather more straightforward than in Rust. The outcomes are much the same, but since <em>all</em> <code>String</code>s in Swift are passed by value (never by reference), you simply don’t have to think about modification—even safe modification!</p> <p>Rust of course had the <code>Copy</code> trait which lets you do this, but the point is that the “ergonomics” are slightly nicer in Swift.</p> <p>Also, the string interpolation Swift does is <em>nice</em>. That’s one thing I really wish Rust had. It’s Python-style string formatting macro is great, but being able to interpolate values (<code>"strings with \(variables)"</code> or even <code>"embedded expressions like \(2 + 4)"</code>) is very nice.</p> <p>Swift’s approach to strings in general seems well-thought-through and gives appropriate levels of attention to the details which make handling complex or non-Western languages much more manageable. As a typography geek, I appreciate this a great deal.</p> <p>That said, since Swift’s strings <em>do</em> handle all those edge cases for Unicode, you lose some standard string access patterns and lose much (maybe all?) insight into the internal structure of the string. That may be good, and may be bad, depending on the circumstance. Like I said: trade-offs.</p> <p>Actually, on reading further, the way Swift handles Unicode strings is pretty nice. It <em>does</em> give you insight into those, via specific methods for different representations. I particularly appreciate that it’s you deal with them as the standalone <code>String</code> type as well as giving you direct access to the code points—and not just one Unicode code point set, but any of <abbr>UTF8</abbr>, <abbr>UTF16</abbr>, or <abbr>UTF32</abbr> (Unicode scalars). Trust Apple to pay close attention to text.</p> <p>Rust’s strings are <em>good</em>, but not quite as sophisticated (presumably for simplicity around the memory mapping). All Rust <code>String</code> or <code>str</code> instances are composed of <abbr>UTF32</abbr> Unicode scalars, encoded as <abbr>UTF8</abbr> sequences. It doesn’t have some of the convenience methods Swift does for getting any of the other representations. That said, I expect this should show up rarely if at all in my ordinary usage. Importantly, the fundamental storage is the same: both use scalars.</p> <p>This was the first section where it didn’t feel like Rust was just a clear overall “winner” over Swift. Some of the trade-offs between the language designs are more apparent here, and I do appreciate the “ergonomics” of Swift in a number of these things.</p> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-iii.html"><strong>Previous:</strong> Operators, including overloading, and thoughts on brevity.</a></li> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-v.html"><strong>Next:</strong> The value (and challenge) of learning languages in parallel.</a></li> </ul> Chris KrychoThu, 10 Sep 2015 21:05:00 -0400tag:v4.chriskrycho.com,2015-09-10:/2015/rust-and-swift-iv.htmlprogramming languagesrustswiftrust-and-swiftRust and Swift (iii)http://v4.chriskrycho.com/2015/rust-and-swift-iii.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past month. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <p>I just hit operators in the Swift book. First question: are operators special syntax, or are they sugar for <code>protocol</code>s? (Every modern language I use or even have played with handles them as sugar for another language construct—Python, Ruby, Io, Elixir, and Rust, to name just a few ranging over a substantial variety of ages and styles.)</p> <p>Oh. I did the requisite digging, and operators are functions (which is okay) defined in the <del>global namespace (<em>:sigh:</em>)</del> <code>Swift</code> module.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> I say “okay” rather than good because the justification offered is that this is the only way to make the operators work as binary operators between existing instances of types. But that elides the fact that, if that’s the case, it is so because of other language design decisions. This seems like a perfect place to use a <code>protocol</code>, but perhaps (unlike Rust’s <code>trait</code>) they’re not sufficiently capable to handle this? That’s an open question; I have no idea about the answer.</p> <p>Interestingly, Rust has several fewer operators than Swift, even apart from those mentioned in my <a href="http://v4.chriskrycho.com/2015/rust-and-swift-ii.html">previous post</a>. It drops the pre- and post-increment operators entirely (as does Python), since their results can always be accomplished in other ways with less potential for confusion. Swift keeps them, no doubt in part because most (Objective) C programs are deeply familiar with them and with idioms associated with them.</p> <p>I learned a few new things about Rust’s operators as well: the Boolean <code>||</code> and <code>&amp;&amp;</code> operators and its bitwise <code>|</code> and <code>&amp;</code> operators differ not only in that the former are <em>short-circuit</em> operators and the latter are not. Obviously you can also do things like bit-wise flag operations with the latter, but the reference emphasizes the short-circuiting behavior. This makes perfect sense, but it wasn’t something I’d ever considered explicitly before.</p> <p>There is no ternary operator in Rust, because of how it handles the relationship between expressions and statements. Swift keeps it. That’s an interesting reflection of differences in design: Rust dropped it because <code>if</code> blocks are expressions, so it’s redundant, and they have had a goal of removing unnecessary features. (See the discussion on dropping the ternary operator—with an interesting aside from Brendan Eich on JavaScript—<a href="https://github.com/rust-lang/rust/issues/1698">here</a>). Note that this is not a criticism of Swift, just an observation, though I do really like Rust’s expression-driven approach.</p> <p>The <code>??</code> “nil coalescing operator”, on the other hand, I actively dislike. This seems like shorthand for the sake of shorthand, partly necessitated by the existing drive toward shorthand with optional types in Swift. Sometimes brevity can lead to decreased clarity. Eliding too much, or subsuming it into shorthand, makes the language harder to hold in your head and requires you to slow down more for parsing each line.</p> <p>Nothing surprising (or different) between the standard boolean operators in the two languages.</p> <p>I wonder how many times the word “concise” (or synonyms of it) appear in the Swift book? It’s increasingly clear to me reading that brevity is one of the primary design goals. Maybe it’s just me, but that actually seems a little weird. Brevity is good so far as it goes, but <em>legibility</em> is much better.</p> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-ii.html"><strong>Previous:</strong> Basic types and the syntax around them.</a></li> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-iv.html"><strong>Next:</strong> Language design tradeoffs, highlighted by string manipulation.</a></li> </ul> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>See edit in discussion of functions and global namespace in <a href="http://v4.chriskrycho.com/2015/rust-and-swift-ii.html">part ii</a>.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoMon, 07 Sep 2015 11:55:00 -0400tag:v4.chriskrycho.com,2015-09-07:/2015/rust-and-swift-iii.htmlprogramming languagesrustswiftrust-and-swiftRust and Swift (ii)http://v4.chriskrycho.com/2015/rust-and-swift-ii.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past month. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p> <hr /> <p>At first blush, I find the extra syntax around optionals in Swift more confusing than helpful. I think this comes down to my preference for a more Python-like approach: “Explicit is better than implicit” and “There should be one– and preferably only one –obvious way to do it” both militate against the multiple different ways you can handle optional values in Swift. <code>Optional</code> types are created in one of two ways:</p> <ul> <li>with the <code>?</code> operator on a type definition, creating an explicitly wrapped type which must be checked in some way.</li> <li>with the <code>!</code> operator on a type definition, creating an “implicitly unwrapped optional” by forcibly unwrapping it (and creating a runtime error if the optional is empty)</li> </ul> <p>After creating an optional, you can get at its contents by:</p> <ul> <li>using the <code>if let</code> or <code>while let</code> constructs to bind the optional value’s non-<code>nil</code> value for a block</li> <li>using the <code>!</code> operator on a variable name, explicitly unwrapping it (and creating a runtime error if the optional is empty)</li> </ul> <p>By contrast, in Rust you always have to explicitly unwrap the item, using the <code>unwrap</code> method or pattern matching. There are no implicitly unwrapped types. Moreover, there is no special syntax around creating optional types in Rust: you just declare them with an <code>Option</code> type or another type that <code>impl</code>s the <code>Option</code> behavior. The “shortcut” behavior around error handling, <code>try!</code>, isn’t special syntax, but application of another standard language construct (in this case, a macro).</p> <p>The discussion of <code>assert</code> in the Swift book re-raises the question about the global namespace:</p> <blockquote> <p>“You write an assertion by calling the global <code>assert(_:_:)</code> function.”</p> </blockquote> <p>This continues to suggest strongly that Swift does in fact have a true global namespace, <em>not</em> an automatically-imported prelude. That can make a big difference for applications in certain spaces (e.g. systems programming), when you might have good reason to want to replace the standard library’s approach with a different one. (See Rust’s <a href="https://doc.rust-lang.org/book/no-stdlib.html"><code>#[no_std]</code></a> docs and the <a href="https://github.com/rust-lang/rfcs/blob/master/text/1184-stabilize-no_std.md">related RFC</a>.)</p> <p><strong>Edit:</strong> “strongly suggests” or no, I have now been <a href="https://twitter.com/jckarter/status/708765262309228544" title="Tweet by one of the Swift developers">reliably informed</a> that I was mistaken—and am happy to have been wrong here. As in Haskell, these functions are implicitly imported and belong to the <code>Swift</code> module.</p> <p>In Rust, <code>assert!</code> is a macro, not a function, which is an interesting but perhaps not <em>especially</em> important distinction in this particular case. (It might be, though; I’d have to see the implementation of each to see how they play out differently.)</p> <p>In any case, this also highlights another large difference between the two: testing is <a href="https://doc.rust-lang.org/stable/book/testing.html">front and center</a> in Rust, and barely receives a mention so far in the Swift book (and isn’t in the table of contents). Having language-level support for testing is a big deal.</p> <p>Language tour and first chapter of the language guide down, my sense is that Swift is a substantially better language than C or C++ (and presumably than Objective C, but since I don’t know that language I can’t speak to it) for app design, but that Rust is a better language yet. Both far more modern than their predecessors, but they approach the same problems in surprisingly different ways, relatively similar syntax notwithstanding. So far, I like the Rust approach better.</p> <p>In particular, more syntax is not my preferred way to tackle these things. Providing good language constructs and primitives on which to build seems better in <em>many</em> ways:</p> <ul> <li>It substantially reduces the cognitive load for the developer, by keeping the number of constructs small and simply varying how they are applied.</li> <li>It increases the quality of those primitives, because it forces the language deadness to make sure they actually address the full problem space.</li> <li>It lets developers approach the same problem in ways the language design team may not have anticipated, and over time the community may find shared conventions that improve on the <code>std</code> approach, and nothing has to change in the language spec (or the compiler!) to adopt those changes.</li> <li>In general, then, it makes change much easier to manage, and change can be community-driven rather than requiring the language design team to manage it.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></li> </ul> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-i.html"><strong>Previous:</strong> Thoughts after reading the introduction to the Swift book.</a></li> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-iii.html"><strong>Next:</strong> Operators, including overloading, and thoughts on brevity.</a></li> </ul> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>This may of course be intentional on Apple’s part with Swift. Maintaining tight control over its tooling is very typical of modern Apple.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoSun, 06 Sep 2015 10:20:00 -0400tag:v4.chriskrycho.com,2015-09-06:/2015/rust-and-swift-ii.htmlrustswiftrust-and-swiftprogramming languagesRust and Swift (i)http://v4.chriskrycho.com/2015/rust-and-swift-i.html<p><i class=editorial>I started writing these responses in a Slack channel of developers I participate in as I worked through the <a href="https://developer.apple.com/swift/">Swift</a> <a href="https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/">book</a>. I realized after a bit that it would make a better blog post than chat room content, so here we are. This is all entirely off-the-cuff: me just thinking out loud as I read; this is by no means expert opinion.</i></p> <p><i class=editorial>I later turned this into the first part of a whole <a href="/rust-and-swift.html">series</a> comparing Rust and Swift!</i></p> <hr /> <ul> <li><p><code>..&lt;</code> – seriously?</p> <p>That has to be one of the most annoying operators I’ve ever seen. It ends up with cognitive noise because <code>&lt;name</code> initially processes as “starting a generic” and you have to re-parse it visually and mentally.</p></li> <li><p>After the first chapter of the Swift book, my impression is “a poor man’s Rust”; my gut feel based on that first pass and everything I’ve seen and read about Swift over the past two years is that it’s roughly what you would get if you took Rust’s syntax and replaced Rust’s hard safety goals with the aim of mapping to ObjC semantics. (To be fair to Apple, that interoperability was probably necessary.)</p></li> <li><p>An example that jumps out at me as immediately illustrative of the difference in approach the languages take is the way you pass structures by reference vs. copy. In Swift, that’s done via two completely distinct language constructs, <code>struct</code>s and <code>class</code>es respectively.</p> <p>In Rust, there is just the <code>struct</code> type to handle both of those. They’re immutable unless you declare them with <code>mut</code>, and you can pass them via copy simply by implementing the <code>Copy</code> <code>trait</code> (which seems roughly analogous to Swift’s <code>protocol</code>, but I’ve not yet dug deeply enough to see how they differ). Those things aren’t baked into the language, but use simpler language building blocks to define behavior into the library.</p></li> <li><p>I saw someone do a write up a while back arguing that Go isn’t a <em>bad</em> language, it just isn’t a <em>good</em> language. My first impression of Swift, after having spent the last month with Rust, is very much along those lines.</p></li> <li><p>Huh. Here’s something that I appreciate about Rust, Haskell, and others now that I didn’t before: there’s a difference between implicitly/automatically importing a prelude or a given set of standard library functions, and having actually global functions. Does Swift actually have functions like <code>print</code> in a global namespace, as the book seems to imply, or they being imported automatically <em>a la</em> Rust/Haskell/etc.?</p> <p><strong>Edit:</strong> it appears Swift does likewise, but that you can’t access the relevant module directly. Which is halfway there.</p></li> <li><p>Hmm. Why have <code>Double</code> <em>and</em> <code>Float</code>—just for ObjC interop, I guess?</p> <p><strong>Edit:</strong> follow-up from a conversation with a friend: it’s because you have 32- and 64-bit architectures out there; sometimes you don’t want 64 bits of floating point precision for that reason. Note that Rust <em>also</em> has this distinction; you can declare things as <code>f32</code> or <code>f64</code>.</p></li> <li><p>Extending the above note on <code>class</code>es and <code>struct</code>s and <code>protocol</code>s vs. Rust’s approach: the same thing is true about <code>extension</code>, which is a distinct concept from implementing a <code>protocol</code>; again, in Rust these are both just handled with a single language construct, <code>impl</code>. That’s not because <code>impl</code> is overloaded, but rather because the underlying language machinery is the same for the two things. (edited)</p></li> <li><p>(I’ve a feeling learning Swift is going to turn me into even more of a Rust fanboy.)</p></li> <li><p>Reading the two books in close sequence like this is proving really productive mentally for thinking about how the two handle the same issues. I’ve never done anything quite like this before, and it’s fascinating.</p></li> <li><p>I have an increased appreciation for Rust’s use of semi-colons to turn expressions into statements, and thereby to distinguish clearly between the two (among other things, allowing for implicit return of anything that’s an expression).</p></li> <li><p>Another interesting comparison: Rust’s <code>match</code> and Swift’s <code>switch</code> and <code>case</code> fill the same role of pattern matching. I’m curious to see how they differ. Does Swift do matching on arbitrary expressions?</p> <p>Also, I see where the syntax choices came from in both, and while I slightly prefer Rust’s, I think both make reasonably good sense; Swift’s will understandably be more familiar to C and ObjC programmers, and that’s a perfectly defensible approach. Seen that way, it is expanding on the C-style construct (even if it’s actually doing something substantially more sophisticated than that under the hood by being a form of actual pattern matching).</p></li> </ul> <hr /> <ul> <li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-ii.html"><strong>Next:</strong> Basic types and the syntax around them.</a></li> </ul> Chris KrychoFri, 04 Sep 2015 22:59:00 -0400tag:v4.chriskrycho.com,2015-09-04:/2015/rust-and-swift-i.htmllisticlesprogramming languagesrustswiftrust-and-swiftHigh- and Low-Level Programming Languageshttp://v4.chriskrycho.com/2015/high-and-low-level-programming-languages.html<p>It occurred to me while listening to <a href="https://edwinb.wordpress.com">Edwin Brady</a> talk about <a href="http://www.idris-lang.org">Idris</a> on the <a href="http://typetheorypodcast.com">Type Theory Podcast</a>,<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> having just spent a few weeks starting to learn <a href="https://www.rust-lang.org">Rust</a>: “low-level” has at least two meanings in software. One is whether something has manual memory management or is garbage collected, reference counted, or otherwise manages memory itself. This is what people often mean when they talk about C, C++, etc. as being “low-level” and languages like Python or Ruby or C♯ being high-level.</p> <p>But then you toss in a language like <a href="https://www.rust-lang.org">Rust</a>, and things start to get a little more complicated. Rust can do the same kind of direct memory management that makes C or C++ a good language for things like writing operating system kernels. [<a href="https://github.com/torvalds/linux">1</a>,<a href="https://en.wikipedia.org/wiki/Architecture_of_Windows_NT">2</a>,<a href="http://www.opensource.apple.com/source/xnu/xnu-2782.10.72/">3</a>] But it is also memory-safe, at least in ordinary usage. Like C♯, you have to be explicit about any unsafe code, with the <code>unsafe</code> keyword on any blocks that do memory management that isn’t safe. And the vast majority of Rust code <em>is</em> safe.</p> <p>More than that, though, Rust <em>feels</em> like a high-level language. It gives you higher-kinded functions, generics, traits-based composition of types, hygienic macros, and the implementation of many important parts the essentials of the language in the library. If you need to patch something, or extend something, you can do that in a straightforward way. In short, it gives you lots of good abstractions like you would expect in a high-level language.</p> <p>Rust is low-level in that you can write (and people are writing) systems-level programs in it. It is high-level in that it lets you express things in ways normally associated with languages like Haskell or OCaml or Python or Ruby. To put it simply: it’s <em>low-level</em> in its ability to address the computer, and <em>high-level</em> in the abstractions it hands to a programmer. That’s a powerful combination, and I hope more languages embrace it in the years to come.</p> <section class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn1" role="doc-endnote"><p>Yes, I know that’s insanely nerdy. What did you expect?<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li> </ol> </section> Chris KrychoFri, 07 Aug 2015 20:00:00 -0400tag:v4.chriskrycho.com,2015-08-07:/2015/high-and-low-level-programming-languages.htmlprogramming languagesrustpythonrubyccplusplus