<story><title>Rust – A hard decision pays off</title><url>https://www.pinecone.io/learn/inside-the-pinecone/#rust-a-hard-decision-pays-off</url></story><parent_chain><item><author>throwaway894345</author><text>I actually don&amp;#x27;t care as much for iterators as I thought I would. Beyond some simpler map().reduce() stuff they tend to fall over pretty fast, and I end up spending too much time trying to make iterator chains work before defaulting to for loops. I also dislike how anemic Rust&amp;#x27;s stdlib is. I&amp;#x27;m sure there are good reasons, but I like that I can just reach for Go&amp;#x27;s stdlib for annotating errors or dealing with JSON. Other than that, I like the API design in Rust&amp;#x27;s stdlib.&lt;p&gt;Here&amp;#x27;s an example where the iterator-chain version is way more complex:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    let posts = read_dir(source_directory)?
        .filter_map(|result| {
            (|| {
                let entry = result?;
                let os_file_name = entry.file_name();
                let file_name = os_file_name.to_string_lossy();
                if Self::is_bundle(&amp;amp;entry)? {
                    self.parse_post_bundle(&amp;amp;file_name, &amp;amp;entry.path())
                        .map(Some)
                } else if file_name.ends_with(MARKDOWN_EXTENSION) {
                    self.parse_post(
                        file_name.trim_end_matches(MARKDOWN_EXTENSION),
                        &amp;amp;mut File::open(&amp;amp;entry.path())?,
                    )
                    .map(Some)
                } else {
                    Ok(None)
                }
            })()
            .transpose()
        })
        .collect::&amp;lt;Result&amp;lt;Vec&amp;lt;_&amp;gt;&amp;gt;&amp;gt;()?;
&lt;/code&gt;&lt;/pre&gt;
Here&amp;#x27;s the imperative version:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    let mut posts = Vec::new();
    for result in read_dir(source_directory)? {
        let entry = result?;
        let os_file_name = entry.file_name();
        let file_name = os_file_name.to_string_lossy();
        if Self::is_bundle(&amp;amp;entry)? {
            posts.push(self.parse_post_bundle(&amp;amp;file_name, &amp;amp;entry.path())?);
        } else if file_name.ends_with(MARKDOWN_EXTENSION) {
            posts.push(self.parse_post(
                file_name.trim_end_matches(MARKDOWN_EXTENSION),
                &amp;amp;mut File::open(&amp;amp;entry.path())?,
            )?);
        }
    }&lt;/code&gt;&lt;/pre&gt;</text></item><item><author>lijogdfljk</author><text>&amp;gt; Use Go if you&amp;#x27;re looking for an easy GC language with max productivity and a decent performance ceiling. Use Rust if you&amp;#x27;re writing really high performance or correctness-is-paramount software.&lt;p&gt;I&amp;#x27;d add one more addition to use Rust (speaking from an ex-Go dev): Use Rust if you want a robust std lib. Go is good, i used it for ~5 years, but man Rust was a breath of fresh air with the amount of tooling that helped me solve problems. Iterators, are a great example.&lt;p&gt;I also preferred Crates vs Github Repos, but i think that&amp;#x27;s just personal preference.. not objective.</text></item><item><author>throwaway894345</author><text>&amp;gt; Dev velocity, which was supposed to be the claim to fame of Python, improved dramatically with Rust.&lt;p&gt;I don&amp;#x27;t doubt this in the least. I&amp;#x27;ve been a professional Python developer for 15 years, and I can&amp;#x27;t believe Python ever had the reputation for &amp;quot;high dev velocity&amp;quot; beyond toy examples. In every real world code base I&amp;#x27;ve worked in, Python has been a strict liability and the promise that you can &amp;quot;just rewrite the slow parts in C&amp;#x2F;C++&amp;#x2F;Numpy&amp;#x2F;etc&amp;quot; has never held (you very often spend at least as much time marshaling the data to the target language format than you gain by processing in the faster language &lt;i&gt;and&lt;/i&gt; you have all of the maintainability problems of C&amp;#x2F;C++&amp;#x2F;Numpy). Python trades developer velocity for poor runtime performance.&lt;p&gt;I don&amp;#x27;t think Rust is the paragon of high dev velocity languages either, but it seems to be more predictable. You don&amp;#x27;t have something that works as a prototype, but then you run into a bunch of performance problems (which virtually cannot be worked around) when you go to productionize, nor do you get all of the emergent quality and maintainability issues that come about from a dynamic type system (and last I checked, Python&amp;#x27;s optional static type system was still pretty alpha-grade).&lt;p&gt;I strongly recommend avoiding Python for new projects. Use Go if you&amp;#x27;re looking for an easy GC language with max productivity and a decent performance ceiling. Use Rust if you&amp;#x27;re writing really high performance or correctness-is-paramount software. I&amp;#x27;m sure there are other decent options as well (I&amp;#x27;ve heard generally good things about TypeScript, but I&amp;#x27;d be concerned about its performance even if it is better than Python).</text></item></parent_chain><comment><author>0x457</author><text>Iterator-chain version would be a lot better looking if it was actually was a chain and not everything pushed into a single `filter_map`. &amp;quot;Ifs&amp;quot; are weird looking, one branch is using `entry`(I take it&amp;#x27;s a `DirEntry`?) and another is using `file_name` I suspect both could use the and look like `Self::is_` ?&lt;p&gt;If you&amp;#x27;re going to write an iterator chain in an imperative way, then you might as well right it imperatively.&lt;p&gt;A few notes:&lt;p&gt;- you can compare `&amp;amp;OsStr` with `&amp;amp;str` without `to_string_lossy` any explicit conversion (`&amp;amp;str -&amp;gt; &amp;amp;OsStr` done in `PartialEq` is basically free)&lt;p&gt;- you can get extension from `Path` by using `Path::extension`&lt;p&gt;- you can get filename without extension by using `Path::file_stem` or `Path::file_prefix`&lt;p&gt;- making your parse functions take the same arguments makes it a lot cleaner&lt;p&gt;Something like this:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    read_dir(&amp;quot;&amp;quot;)?
    .map(|e| e.map(|e| e.path()))
    .map(|path| {
        path.and_then(|path| {
            if Self::is_bundle(&amp;amp;path) {
                self.parse_post_bundle(&amp;amp;path.file_name().to_string_lossy(), &amp;amp;path).map(Some)
            } else if Self::is_markdown(&amp;amp;path) {
                self.parse_post(&amp;amp;path.file_stem().to_string_lossy(), &amp;amp;path).map(Some)

            } else {
                Ok(None)
            }
        })
    })
    .filter_map(Result::transpose)
    .collect::&amp;lt;Result&amp;lt;Vec&amp;lt;()&amp;gt;, std::io::Error&amp;gt;&amp;gt;()

    &amp;#x2F;&amp;#x2F; Ignore this, just an example
    fn is_bundle(path: &amp;amp;Path) -&amp;gt; bool {
        path.extension().map(|ext| ext == &amp;quot;bundle&amp;quot;).unwrap_or(false)
    }
    
    fn is_markdown(path: &amp;amp;Path) -&amp;gt; bool {
        path.extension().map(|ext| ext == &amp;quot;md&amp;quot;).unwrap_or(false)
    }&lt;/code&gt;&lt;/pre&gt;</text></comment>
<story><title>Rust – A hard decision pays off</title><url>https://www.pinecone.io/learn/inside-the-pinecone/#rust-a-hard-decision-pays-off</url></story><parent_chain><item><author>throwaway894345</author><text>I actually don&amp;#x27;t care as much for iterators as I thought I would. Beyond some simpler map().reduce() stuff they tend to fall over pretty fast, and I end up spending too much time trying to make iterator chains work before defaulting to for loops. I also dislike how anemic Rust&amp;#x27;s stdlib is. I&amp;#x27;m sure there are good reasons, but I like that I can just reach for Go&amp;#x27;s stdlib for annotating errors or dealing with JSON. Other than that, I like the API design in Rust&amp;#x27;s stdlib.&lt;p&gt;Here&amp;#x27;s an example where the iterator-chain version is way more complex:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    let posts = read_dir(source_directory)?
        .filter_map(|result| {
            (|| {
                let entry = result?;
                let os_file_name = entry.file_name();
                let file_name = os_file_name.to_string_lossy();
                if Self::is_bundle(&amp;amp;entry)? {
                    self.parse_post_bundle(&amp;amp;file_name, &amp;amp;entry.path())
                        .map(Some)
                } else if file_name.ends_with(MARKDOWN_EXTENSION) {
                    self.parse_post(
                        file_name.trim_end_matches(MARKDOWN_EXTENSION),
                        &amp;amp;mut File::open(&amp;amp;entry.path())?,
                    )
                    .map(Some)
                } else {
                    Ok(None)
                }
            })()
            .transpose()
        })
        .collect::&amp;lt;Result&amp;lt;Vec&amp;lt;_&amp;gt;&amp;gt;&amp;gt;()?;
&lt;/code&gt;&lt;/pre&gt;
Here&amp;#x27;s the imperative version:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    let mut posts = Vec::new();
    for result in read_dir(source_directory)? {
        let entry = result?;
        let os_file_name = entry.file_name();
        let file_name = os_file_name.to_string_lossy();
        if Self::is_bundle(&amp;amp;entry)? {
            posts.push(self.parse_post_bundle(&amp;amp;file_name, &amp;amp;entry.path())?);
        } else if file_name.ends_with(MARKDOWN_EXTENSION) {
            posts.push(self.parse_post(
                file_name.trim_end_matches(MARKDOWN_EXTENSION),
                &amp;amp;mut File::open(&amp;amp;entry.path())?,
            )?);
        }
    }&lt;/code&gt;&lt;/pre&gt;</text></item><item><author>lijogdfljk</author><text>&amp;gt; Use Go if you&amp;#x27;re looking for an easy GC language with max productivity and a decent performance ceiling. Use Rust if you&amp;#x27;re writing really high performance or correctness-is-paramount software.&lt;p&gt;I&amp;#x27;d add one more addition to use Rust (speaking from an ex-Go dev): Use Rust if you want a robust std lib. Go is good, i used it for ~5 years, but man Rust was a breath of fresh air with the amount of tooling that helped me solve problems. Iterators, are a great example.&lt;p&gt;I also preferred Crates vs Github Repos, but i think that&amp;#x27;s just personal preference.. not objective.</text></item><item><author>throwaway894345</author><text>&amp;gt; Dev velocity, which was supposed to be the claim to fame of Python, improved dramatically with Rust.&lt;p&gt;I don&amp;#x27;t doubt this in the least. I&amp;#x27;ve been a professional Python developer for 15 years, and I can&amp;#x27;t believe Python ever had the reputation for &amp;quot;high dev velocity&amp;quot; beyond toy examples. In every real world code base I&amp;#x27;ve worked in, Python has been a strict liability and the promise that you can &amp;quot;just rewrite the slow parts in C&amp;#x2F;C++&amp;#x2F;Numpy&amp;#x2F;etc&amp;quot; has never held (you very often spend at least as much time marshaling the data to the target language format than you gain by processing in the faster language &lt;i&gt;and&lt;/i&gt; you have all of the maintainability problems of C&amp;#x2F;C++&amp;#x2F;Numpy). Python trades developer velocity for poor runtime performance.&lt;p&gt;I don&amp;#x27;t think Rust is the paragon of high dev velocity languages either, but it seems to be more predictable. You don&amp;#x27;t have something that works as a prototype, but then you run into a bunch of performance problems (which virtually cannot be worked around) when you go to productionize, nor do you get all of the emergent quality and maintainability issues that come about from a dynamic type system (and last I checked, Python&amp;#x27;s optional static type system was still pretty alpha-grade).&lt;p&gt;I strongly recommend avoiding Python for new projects. Use Go if you&amp;#x27;re looking for an easy GC language with max productivity and a decent performance ceiling. Use Rust if you&amp;#x27;re writing really high performance or correctness-is-paramount software. I&amp;#x27;m sure there are other decent options as well (I&amp;#x27;ve heard generally good things about TypeScript, but I&amp;#x27;d be concerned about its performance even if it is better than Python).</text></item></parent_chain><comment><author>thinkharderdev</author><text>Yep, agree wholeheartedly with this. I came to Rust from Scala where writing an explicit for loop is looked at as one step above using goto :) and it took me a while to just give in and write the imperative version.</text></comment>